├── .gitignore ├── LICENSE ├── LICENSE (Memcached customizations) ├── README.md ├── bmc ├── .gitignore ├── Makefile ├── bmc_common.h ├── bmc_kern.c └── bmc_user.c ├── env.sh ├── kernel-src-download.sh ├── kernel-src-prepare.sh ├── kernel-src-remove.sh └── memcached-sr ├── .gitignore ├── .shipit ├── .travis.yml ├── AUTHORS ├── BUILD ├── CONTRIBUTING.md ├── COPYING ├── ChangeLog ├── Doxyfile ├── HACKING ├── LICENSE.bipbuffer ├── LICENSE.itoa_ljust ├── LICENSE.orig ├── Makefile.am ├── NEWS ├── README.md ├── assoc.c ├── assoc.h ├── authfile.c ├── authfile.h ├── autogen.sh ├── bipbuffer.c ├── bipbuffer.h ├── cache.c ├── cache.h ├── configure.ac ├── crawler.c ├── crawler.h ├── crc32c.c ├── crc32c.h ├── daemon.c ├── devtools ├── Dockerfile.alpine ├── Dockerfile.arch ├── Dockerfile.fedora ├── Dockerfile.ubuntu ├── bench_noreply.pl ├── clean-whitespace.pl └── slab_loadgen ├── doc ├── CONTRIBUTORS ├── Doxyfile ├── Makefile.am ├── memcached.1 ├── new_lru.txt ├── protocol-binary-range.xml ├── protocol-binary.xml ├── protocol.txt ├── readme.txt ├── storage.txt ├── threads.txt ├── tls.txt └── xml2rfc │ ├── reference.RFC.0768.xml │ ├── reference.RFC.2119.xml │ ├── rfc2629-noinc.xsl │ ├── rfc2629-other.ent │ ├── rfc2629-refchk.xsl │ ├── rfc2629-xhtml.ent │ └── rfc2629.dtd ├── docker-compose.yml ├── extstore.c ├── extstore.h ├── freebsd_priv.c ├── globals.c ├── hash.c ├── hash.h ├── items.c ├── items.h ├── itoa_ljust.c ├── itoa_ljust.h ├── jenkins_hash.c ├── jenkins_hash.h ├── linux_priv.c ├── logger.c ├── logger.h ├── m4 └── c99-backport.m4 ├── memcached.c ├── memcached.h ├── memcached.spec.in ├── memcached_dtrace.d ├── murmur3_hash.c ├── murmur3_hash.h ├── openbsd_priv.c ├── protocol_binary.h ├── restart.c ├── restart.h ├── sasl_defs.c ├── sasl_defs.h ├── scripts ├── README.damemtop ├── damemtop ├── damemtop.yaml ├── memcached-automove ├── memcached-automove-extstore ├── memcached-init ├── memcached-server.upstart ├── memcached-tool ├── memcached-tool.1 ├── memcached.service ├── memcached.sysconfig ├── memcached.sysv ├── memcached.upstart ├── memcached@.service └── start-memcached ├── sizes.c ├── slab_automove.c ├── slab_automove.h ├── slab_automove_extstore.c ├── slab_automove_extstore.h ├── slabs.c ├── slabs.h ├── solaris_priv.c ├── stats.c ├── stats.h ├── storage.c ├── storage.h ├── t ├── 00-startup.t ├── 64bit.t ├── ascii-auth.t ├── authfile ├── binary-extstore.t ├── binary-get.t ├── binary-sasl.t ├── binary.t ├── bogus-commands.t ├── cacert.pem ├── cakey.pem ├── cas.t ├── chunked-extstore.t ├── chunked-items.t ├── client_crt.pem ├── client_key.pem ├── daemonize.t ├── dash-M.t ├── dyn-maxbytes.t ├── error-extstore.t ├── evictions.t ├── expirations.t ├── extstore-buckets.t ├── extstore-jbod.t ├── extstore.t ├── flags.t ├── flush-all.t ├── getandtouch.t ├── getset.t ├── idle-timeout.t ├── incrdecr.t ├── issue_104.t ├── issue_108.t ├── issue_14.t ├── issue_140.t ├── issue_152.t ├── issue_163.t ├── issue_183.t ├── issue_192.t ├── issue_22.t ├── issue_260.t ├── issue_29.t ├── issue_3.t ├── issue_41.t ├── issue_42.t ├── issue_50.t ├── issue_61.t ├── issue_67.t ├── issue_68.t ├── issue_70.t ├── item_size_max.t ├── lib │ └── MemcachedTest.pm ├── line-lengths.t ├── lru-crawler.t ├── lru-maintainer.t ├── lru.t ├── malicious-commands.t ├── maxconns.t ├── metaget.t ├── misbehave.t ├── multiversioning.t ├── noreply.t ├── quit.t ├── refhang.t ├── restart.t ├── sasl │ └── memcached.conf ├── server.pem ├── server_crt.pem ├── server_key.pem ├── slabhang.t ├── slabs-reassign-chunked.t ├── slabs-reassign2.t ├── slabs_reassign.t ├── ssl_cert_refresh.t ├── ssl_ports.t ├── ssl_settings.t ├── ssl_verify_modes.t ├── stats-conns.t ├── stats-detail.t ├── stats.t ├── stress-memcached.pl ├── touch.t ├── udp.t ├── unixsocket.t ├── watcher.t ├── watcher_connid.t └── whitespace.t ├── testapp.c ├── thread.c ├── timedrun.c ├── tls.c ├── tls.h ├── trace.h ├── util.c ├── util.h ├── version.pl └── version.sh /.gitignore: -------------------------------------------------------------------------------- 1 | linux-*.tar.xz 2 | linux-*.tar.gz 3 | linux-*.tar.sign 4 | -------------------------------------------------------------------------------- /LICENSE (Memcached customizations): -------------------------------------------------------------------------------- 1 | Copyright (c) 2021, Orange SA 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the University of California, Berkeley nor the 15 | names of its contributors may be used to endorse or promote products 16 | derived from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY 19 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 22 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /bmc/.gitignore: -------------------------------------------------------------------------------- 1 | /linux 2 | *.ll 3 | *.o 4 | bmc 5 | -------------------------------------------------------------------------------- /bmc/bmc_common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Software Name : bmc-cache 3 | * SPDX-FileCopyrightText: Copyright (c) 2021 Orange 4 | * SPDX-License-Identifier: LGPL-2.1-only 5 | * 6 | * This software is distributed under the 7 | * GNU Lesser General Public License v2.1 only. 8 | * 9 | * Author: Yoann GHIGOFF et al. 10 | */ 11 | 12 | #ifndef _BMC_COMMON_H 13 | #define _BMC_COMMON_H 14 | 15 | #define BMC_MAX_KEY_LENGTH 250 16 | #define BMC_MAX_VAL_LENGTH 1000 17 | #define BMC_MAX_ADDITIONAL_PAYLOAD_BYTES 53 18 | #define BMC_MAX_CACHE_DATA_SIZE BMC_MAX_KEY_LENGTH+BMC_MAX_VAL_LENGTH+BMC_MAX_ADDITIONAL_PAYLOAD_BYTES 19 | #define BMC_MAX_KEY_IN_MULTIGET 30 20 | #define BMC_CACHE_ENTRY_COUNT 3250000 21 | #define BMC_MAX_PACKET_LENGTH 1500 22 | #define BMC_MAX_KEY_IN_PACKET BMC_MAX_KEY_IN_MULTIGET 23 | 24 | #define FNV_OFFSET_BASIS_32 2166136261 25 | #define FNV_PRIME_32 16777619 26 | 27 | enum { 28 | BMC_PROG_XDP_HASH_KEYS = 0, 29 | BMC_PROG_XDP_PREPARE_PACKET, 30 | BMC_PROG_XDP_WRITE_REPLY, 31 | BMC_PROG_XDP_INVALIDATE_CACHE, 32 | 33 | BMC_PROG_XDP_MAX 34 | }; 35 | 36 | enum { 37 | BMC_PROG_TC_UPDATE_CACHE = 0, 38 | 39 | BMC_PROG_TC_MAX 40 | }; 41 | 42 | 43 | struct bmc_cache_entry { 44 | struct bpf_spin_lock lock; 45 | unsigned int len; 46 | char valid; 47 | int hash; 48 | char data[BMC_MAX_CACHE_DATA_SIZE]; 49 | }; 50 | 51 | struct bmc_stats { 52 | unsigned int get_recv_count; // Number of GET command received 53 | unsigned int set_recv_count; // Number of SET command received 54 | unsigned int get_resp_count; // Number of GET command reply analyzed 55 | unsigned int hit_misprediction; // Number of keys that were expected to hit but did not (either because of a hash colision or a race with an invalidation/update) 56 | unsigned int hit_count; // Number of HIT in kernel cache 57 | unsigned int miss_count; // Number of MISS in kernel cache 58 | unsigned int update_count; // Number of kernel cache updates 59 | unsigned int invalidation_count; // Number of kernel cache entry invalidated 60 | }; 61 | 62 | #endif 63 | -------------------------------------------------------------------------------- /env.sh: -------------------------------------------------------------------------------- 1 | BMCCACHE_BASE_PATH="$(readlink -f $( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd ))" 2 | BMCCACHE_KERNEL_VERSION="5.3" 3 | BMCCACHE_KERNEL_TARXZ="${BMCCACHE_BASE_PATH}/linux-${BMCCACHE_KERNEL_VERSION}.tar.xz" 4 | BMCCACHE_BMC_PATH="${BMCCACHE_BASE_PATH}/bmc" 5 | -------------------------------------------------------------------------------- /kernel-src-prepare.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # -------------------- 3 | # Run this script to extract and generate kernel sources files required to compile BMC 4 | # -------------------- 5 | source "$(dirname "$(readlink -f "$0")")/env.sh" 6 | 7 | echo "Extracting kernel sources to ${BMCCACHE_BMC_PATH}/linux" 8 | if tar xf ${BMCCACHE_KERNEL_TARXZ} -C ${BMCCACHE_BMC_PATH} && mv ${BMCCACHE_BMC_PATH}/linux-${BMCCACHE_KERNEL_VERSION} ${BMCCACHE_BMC_PATH}/linux; then 9 | echo "Successfully extracted kernel sources to ${BMCCACHE_BMC_PATH}/linux" 10 | else 11 | echo "Failed to extract kernel sources" 12 | exit 1 13 | fi 14 | 15 | echo "Preparing kernel sources" 16 | if make -C ${BMCCACHE_BMC_PATH}/linux defconfig && make -C ${BMCCACHE_BMC_PATH}/linux prepare; then 17 | echo "Done preparing kernel sources" 18 | else 19 | echo "Failed to prepare kernel sources" 20 | exit 1 21 | fi 22 | -------------------------------------------------------------------------------- /kernel-src-remove.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # -------------------- 3 | # Run this script to delete downloaded kernel sources 4 | # -------------------- 5 | source "$(dirname "$(readlink -f "$0")")/env.sh" 6 | 7 | if [[ -f ${BMCCACHE_KERNEL_TARXZ} ]]; then 8 | echo "Deleting ${BMCCACHE_KERNEL_TARXZ}" 9 | rm -rf ${BMCCACHE_KERNEL_TARXZ} 10 | fi 11 | 12 | if [[ -d "${BMCCACHE_BMC_PATH}/linux" ]]; then 13 | echo "Deleting ${BMCCACHE_BMC_PATH}/linux" 14 | rm -rf "${BMCCACHE_BMC_PATH}/linux" 15 | fi 16 | 17 | echo "Finished cleaning up." 18 | -------------------------------------------------------------------------------- /memcached-sr/.gitignore: -------------------------------------------------------------------------------- 1 | *.[aois] 2 | *.gcov 3 | *.gcda 4 | *.gcno 5 | *.tcov 6 | .deps 7 | .buildbot 8 | INSTALL 9 | Makefile 10 | Makefile.in 11 | config.guess 12 | config.h 13 | config.h.in 14 | config.log 15 | config.status 16 | config.sub 17 | aclocal.m4 18 | compile 19 | autom4te.cache 20 | configure 21 | depcomp 22 | install-sh 23 | memcached 24 | memcached-debug 25 | memcached-debug.profile 26 | missing 27 | stamp-h1 28 | tags 29 | TAGS 30 | cscope.out 31 | memcached_dtrace.h 32 | *~ 33 | memcached-*.tar.gz 34 | memcached-*.tar.gz.sha1 35 | doc/protocol-binary-range.txt 36 | doc/protocol-binary.txt 37 | /sizes 38 | /version.m4 39 | /version.num 40 | /testapp 41 | /timedrun 42 | /doc/doxy 43 | /memcached.spec 44 | .*.swp 45 | /compile_commands.json 46 | -------------------------------------------------------------------------------- /memcached-sr/.shipit: -------------------------------------------------------------------------------- 1 | steps = FindVersion, ChangeVersion, CheckChangeLog, DistTest, Commit, Tag, MakeDist, AddToSVNDir 2 | 3 | AddToSVNDir.dir = ../website/dist 4 | svn.tagpattern = %v 5 | -------------------------------------------------------------------------------- /memcached-sr/.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: xenial 3 | language: cpp 4 | 5 | compiler: 6 | - gcc 7 | 8 | install: 9 | - sudo apt-get update -y 10 | - sudo apt-get install -y build-essential automake1.11 autoconf libevent-dev libseccomp-dev git tar wget libio-socket-ssl-perl 11 | - wget https://www.openssl.org/source/openssl-1.1.0g.tar.gz && tar xzvf openssl-1.1.0g.tar.gz 12 | - cd openssl-1.1.0g && ./config -Wl,--enable-new-dtags,-rpath,'$(LIBRPATH)' && make && sudo make install && openssl version && cd ../ 13 | - rm -rf openssl-1.1.0g && rm openssl-1.1.0g.tar.gz* 14 | 15 | script: 16 | - ./autogen.sh 17 | - ./configure --enable-seccomp --enable-tls 18 | - make -j 19 | - make test 20 | - make test_tls 21 | -------------------------------------------------------------------------------- /memcached-sr/AUTHORS: -------------------------------------------------------------------------------- 1 | Anatoly Vorobey 2 | Brad Fitzpatrick 3 | -------------------------------------------------------------------------------- /memcached-sr/BUILD: -------------------------------------------------------------------------------- 1 | Ideally, you want to make a static binary, otherwise the dynamic 2 | linker pollutes your address space with shared libs right in the 3 | middle. (NOTE: actually, this shouldn't matter so much anymore, now 4 | that we only allocate huge, fixed-size slabs) 5 | 6 | Make sure your libevent has epoll (Linux) or kqueue (BSD) support. 7 | Using poll or select only is slow, and works for testing, but 8 | shouldn't be used for high-traffic memcache installations. 9 | 10 | To build libevent with epoll on Linux, you need two things. First, 11 | you need /usr/include/sys/epoll.h . To get it, you can install the 12 | userspace epoll library, epoll-lib. The link to the latest version 13 | is buried inside 14 | http://www.xmailserver.org/linux-patches/nio-improve.html ; currently 15 | it's http://www.xmailserver.org/linux-patches/epoll-lib-0.9.tar.gz . 16 | If you're having any trouble building/installing it, you can just copy 17 | epoll.h from that tarball to /usr/include/sys as that's the only thing 18 | from there that libevent really needs. 19 | 20 | Secondly, you need to declare syscall numbers of epoll syscalls, so 21 | libevent can use them. Put these declarations somewhere 22 | inside : 23 | 24 | #define __NR_epoll_create 254 25 | #define __NR_epoll_ctl 255 26 | #define __NR_epoll_wait 256 27 | 28 | After this you should be able to build libevent with epoll support. 29 | Once you build/install libevent, you don't need to 30 | compile memcache or link it against libevent. Don't forget that for epoll 31 | support to actually work at runtime you need to use a kernel with epoll 32 | support patch applied, as explained in the README file. 33 | 34 | BSD users are luckier, and will get kqueue support by default. 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /memcached-sr/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | See: https://github.com/memcached/memcached/wiki/DevelopmentRepos 2 | 3 | It's worth repeating here, that the biggest contribution anyone can make is to 4 | help run new releases! Any feedback we get is greatly appreciated. Hard to 5 | know what to work on and what to prioritize if we don't hear from you :) 6 | 7 | The easiest thing to do is to run the latest version on one machine in your 8 | cluster sometimes. Then when you do need to upgrade, you should also have 9 | confidence in a well tested version. 10 | -------------------------------------------------------------------------------- /memcached-sr/COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2003, Danga Interactive, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following disclaimer 13 | in the documentation and/or other materials provided with the 14 | distribution. 15 | 16 | * Neither the name of the Danga Interactive nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /memcached-sr/HACKING: -------------------------------------------------------------------------------- 1 | * Hacking Memcached 2 | 3 | * Prerequisites 4 | 5 | - autoconf 6 | - automake 7 | - autotools 8 | - libevent 9 | 10 | * Getting Started 11 | 12 | After checking out a git repository, you must first run autogen.sh 13 | once in order to create the configure script. 14 | 15 | Next, run the configure script and start doing builds. 16 | 17 | IE: 18 | ./autogen.sh && ./configure && make && make test 19 | 20 | * Setting up Git 21 | 22 | Though not required, there are a couple of things you can add to git 23 | to help development. 24 | 25 | ** Pre Commit Hook 26 | 27 | The pre-commit hook can be used to ensure that your tree passes tests 28 | before allowing a commit. To do so, add the following to 29 | .git/hooks/pre-commit (which must be executable): 30 | 31 | #!/bin/sh 32 | make test 33 | 34 | ** Post Commit Hook 35 | 36 | Because the version number changes on each commit, it's good to use a 37 | post commit hook to update the version number after each commit so as 38 | to keep the reporting accurate. To do so, add the following to 39 | .git/hooks/post-commit (which must be executable) 40 | 41 | #!/bin/sh 42 | ./version.sh 43 | 44 | ** Running memcached in gdb for tests. 45 | 46 | By default `make test` will spawn a memcached daemon for each test. 47 | This doesn't let you easily drop into gdb or run verbosely. 48 | 49 | If you export the environment variable 50 | T_MEMD_USE_DAEMON="127.0.0.1:11211" the tests will use an existing 51 | daemon at that address. 52 | 53 | * Debugging seccomp issues 54 | 55 | If new functionality fails when built with seccomp / drop privileges 56 | support, it can be debugged in one of two ways: 57 | 58 | Run the memcached via strace. For example: 59 | 60 | strace -o /tmp/memcache.strace -f -- ./memcached 61 | less /tmp/memcache.strace 62 | 63 | And look for calls which failed due to access restriction. They will 64 | show up with result: "-1 (errno 13)". Then add them to linux_priv.c. 65 | 66 | Alternatively, change the definition in linux_priv.c to: 67 | 68 | #define DENY_ACTION SCMP_ACT_TRAP 69 | 70 | and the process will crash with a coredump on all policy violations. 71 | In strace output those can be seen as: 72 | 73 | SIGSYS {si_signo=SIGSYS, si_code=SYS_SECCOMP, 74 | si_call_addr=0x358a443454d, si_syscall=__NR_write, 75 | si_arch=AUDIT_ARCH_X86_64} --- 76 | 77 | In that output, the si_syscall shows which operation has been 78 | blocked. In this case that's `write()`. 79 | 80 | * Sending patches 81 | 82 | See current instructions at https://github.com/memcached/memcached/wiki/DevelopmentRepos 83 | -------------------------------------------------------------------------------- /memcached-sr/LICENSE.bipbuffer: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, Willem-Hendrik Thiart 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * The names of its contributors may not be used to endorse or promote 12 | products derived from this software without specific prior written 13 | permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL WILLEM-HENDRIK THIART BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | -------------------------------------------------------------------------------- /memcached-sr/LICENSE.itoa_ljust: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016, Arturo Martin-de-Nicolas 2 | arturomdn@gmail.com 3 | https://github.com/amdn/itoa_ljust/ 4 | All rights reserved. 5 | 6 | This implementation is loosely based on the structure of FastInt32ToBufferLeft 7 | in: 8 | 9 | Protocol Buffers - Google's data interchange format 10 | Copyright 2008 Google Inc. All rights reserved. 11 | https://developers.google.com/protocol-buffers/ 12 | 13 | Redistribution and use in source and binary forms, with or without 14 | modification, are permitted provided that the following conditions are 15 | met: 16 | 17 | * Redistributions of source code must retain the above copyright 18 | notice, this list of conditions and the following disclaimer. 19 | 20 | * Redistributions in binary form must reproduce the above 21 | copyright notice, this list of conditions and the following disclaimer 22 | in the documentation and/or other materials provided with the 23 | distribution. 24 | 25 | * Neither the name of Google Inc. nor the names of its 26 | contributors may be used to endorse or promote products derived from 27 | this software without specific prior written permission. 28 | 29 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 | -------------------------------------------------------------------------------- /memcached-sr/LICENSE.orig: -------------------------------------------------------------------------------- 1 | Copyright (c) 2003, Danga Interactive, Inc. 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | * Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | * Redistributions in binary form must reproduce the above 12 | copyright notice, this list of conditions and the following disclaimer 13 | in the documentation and/or other materials provided with the 14 | distribution. 15 | 16 | * Neither the name of the Danga Interactive nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | -------------------------------------------------------------------------------- /memcached-sr/NEWS: -------------------------------------------------------------------------------- 1 | https://memcached.org/ 2 | -------------------------------------------------------------------------------- /memcached-sr/README.md: -------------------------------------------------------------------------------- 1 | # Memcached 2 | 3 | Memcached is a high performance multithreaded event-based key/value cache 4 | store intended to be used in a distributed system. 5 | 6 | See: https://memcached.org/about 7 | 8 | A fun story explaining usage: https://memcached.org/tutorial 9 | 10 | If you're having trouble, try the wiki: https://memcached.org/wiki 11 | 12 | If you're trying to troubleshoot odd behavior or timeouts, see: 13 | https://memcached.org/timeouts 14 | 15 | https://memcached.org/ is a good resource in general. Please use the mailing 16 | list to ask questions, github issues aren't seen by everyone! 17 | 18 | ## Dependencies 19 | 20 | * libevent, https://www.monkey.org/~provos/libevent/ (libevent-dev) 21 | * libseccomp, (optional, experimental, linux) - enables process restrictions for 22 | better security. Tested only on x86_64 architectures. 23 | 24 | ## Environment 25 | 26 | Be warned that the -k (mlockall) option to memcached might be 27 | dangerous when using a large cache. Just make sure the memcached machines 28 | don't swap. memcached does non-blocking network I/O, but not disk. (it 29 | should never go to disk, or you've lost the whole point of it) 30 | 31 | ## Website 32 | 33 | * https://www.memcached.org 34 | 35 | ## Contributing 36 | 37 | See https://github.com/memcached/memcached/wiki/DevelopmentRepos 38 | -------------------------------------------------------------------------------- /memcached-sr/assoc.h: -------------------------------------------------------------------------------- 1 | /* associative array */ 2 | void assoc_init(const int hashpower_init); 3 | item *assoc_find(const char *key, const size_t nkey, const uint32_t hv); 4 | int assoc_insert(item *item, const uint32_t hv); 5 | void assoc_delete(const char *key, const size_t nkey, const uint32_t hv); 6 | void do_assoc_move_next_bucket(void); 7 | int start_assoc_maintenance_thread(void); 8 | void stop_assoc_maintenance_thread(void); 9 | void assoc_start_expand(uint64_t curr_items); 10 | extern unsigned int hashpower; 11 | extern unsigned int item_lock_hashpower; 12 | -------------------------------------------------------------------------------- /memcached-sr/authfile.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "authfile.h" 10 | 11 | // TODO: frontend needs a refactor so this can avoid global objects. 12 | 13 | #define MAX_ENTRY_LEN 256 14 | // Not supposed to be a huge database! 15 | #define MAX_ENTRIES 8 16 | 17 | typedef struct auth_entry { 18 | char *user; 19 | size_t ulen; 20 | char *pass; 21 | size_t plen; 22 | } auth_t; 23 | 24 | auth_t main_auth_entries[MAX_ENTRIES]; 25 | int entry_cnt = 0; 26 | char *main_auth_data = NULL; 27 | 28 | enum authfile_ret authfile_load(const char *file) { 29 | struct stat sb; 30 | char *auth_data = NULL; 31 | auth_t auth_entries[MAX_ENTRIES]; 32 | 33 | if (stat(file, &sb) == -1) { 34 | return AUTHFILE_MISSING; 35 | } 36 | 37 | auth_data = calloc(1, sb.st_size); 38 | 39 | if (auth_data == NULL) { 40 | return AUTHFILE_OOM; 41 | } 42 | 43 | FILE *pwfile = fopen(file, "r"); 44 | if (pwfile == NULL) { 45 | // not strictly necessary but to be safe. 46 | free(auth_data); 47 | return AUTHFILE_OPENFAIL; 48 | } 49 | 50 | char *auth_cur = auth_data; 51 | auth_t *entry_cur = auth_entries; 52 | int used = 0; 53 | 54 | while ((fgets(auth_cur, MAX_ENTRY_LEN, pwfile)) != NULL) { 55 | int x; 56 | int found = 0; 57 | 58 | for (x = 0; x < MAX_ENTRY_LEN; x++) { 59 | if (!found && auth_cur[x] == ':') { 60 | entry_cur->user = auth_cur; 61 | entry_cur->ulen = x; 62 | entry_cur->pass = &auth_cur[x+1]; 63 | found = 1; 64 | } else if (found) { 65 | // Find end of password. 66 | if (auth_cur[x] == '\n' || 67 | auth_cur[x] == '\r' || 68 | auth_cur[x] == '\0') { 69 | entry_cur->plen = x - (entry_cur->ulen + 1); 70 | break; 71 | } 72 | } 73 | } 74 | 75 | // malformed line. 76 | if (!found) { 77 | (void)fclose(pwfile); 78 | free(auth_data); 79 | return AUTHFILE_MALFORMED; 80 | } 81 | 82 | // FIXME: no silent truncation. 83 | if (++used == MAX_ENTRIES) { 84 | break; 85 | } 86 | // EOF 87 | if (auth_cur[x] == '\0') 88 | break; 89 | 90 | auth_cur += x; 91 | entry_cur++; 92 | } 93 | 94 | // swap the main pointer out now, so if there's an error reloading we 95 | // don't break the existing authentication. 96 | if (main_auth_data != NULL) { 97 | free(main_auth_data); 98 | } 99 | 100 | entry_cnt = used; 101 | main_auth_data = auth_data; 102 | memcpy(main_auth_entries, auth_entries, sizeof(auth_entries)); 103 | 104 | (void)fclose(pwfile); 105 | 106 | return AUTHFILE_OK; 107 | } 108 | 109 | // if only loading the file could be this short... 110 | int authfile_check(const char *user, const char *pass) { 111 | size_t ulen = strlen(user); 112 | size_t plen = strlen(pass); 113 | 114 | for (int x = 0; x < entry_cnt; x++) { 115 | auth_t *e = &main_auth_entries[x]; 116 | if (ulen == e->ulen && plen == e->plen && 117 | memcmp(user, e->user, e->ulen) == 0 && 118 | memcmp(pass, e->pass, e->plen) == 0) { 119 | return 1; 120 | } 121 | } 122 | 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /memcached-sr/authfile.h: -------------------------------------------------------------------------------- 1 | #ifndef AUTHFILE_H 2 | #define AUTHFILE_H 3 | 4 | enum authfile_ret { 5 | AUTHFILE_OK = 0, 6 | AUTHFILE_MISSING, 7 | AUTHFILE_OOM, 8 | AUTHFILE_OPENFAIL, 9 | AUTHFILE_MALFORMED, 10 | }; 11 | 12 | // FIXME: mc_authfile or something? 13 | enum authfile_ret authfile_load(const char *file); 14 | int authfile_check(const char *user, const char *pass); 15 | 16 | #endif /* AUTHFILE_H */ 17 | -------------------------------------------------------------------------------- /memcached-sr/autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Get the initial version. 4 | perl version.pl 5 | 6 | die() { 7 | echo "$@" 8 | exit 1 9 | } 10 | 11 | # Try to locate a program by using which, and verify that the file is an 12 | # executable 13 | locate_binary() { 14 | for f in $@ 15 | do 16 | file=`which $f 2>/dev/null | grep -v '^no '` 17 | if test -n "$file" -a -x "$file"; then 18 | echo $file 19 | return 0 20 | fi 21 | done 22 | 23 | echo "" 24 | return 1 25 | } 26 | 27 | echo "aclocal..." 28 | if test x$ACLOCAL = x; then 29 | ACLOCAL=`locate_binary aclocal-1.14 aclocal-1.13 aclocal-1.12 aclocal-1.11 aclocal-1.10 aclocal-1.9 aclocal19 aclocal-1.7 aclocal17 aclocal-1.5 aclocal15 aclocal` 30 | if test x$ACLOCAL = x; then 31 | die "Did not find a supported aclocal" 32 | fi 33 | fi 34 | $ACLOCAL || exit 1 35 | 36 | echo "autoheader..." 37 | AUTOHEADER=${AUTOHEADER:-autoheader} 38 | $AUTOHEADER || exit 1 39 | 40 | echo "automake..." 41 | if test x$AUTOMAKE = x; then 42 | AUTOMAKE=`locate_binary automake-1.14 automake-1.13 automake-1.12 automake-1.11 automake-1.10 automake-1.9 automake-1.7 automake` 43 | if test x$AUTOMAKE = x; then 44 | die "Did not find a supported automake" 45 | fi 46 | fi 47 | $AUTOMAKE --foreign --add-missing || $AUTOMAKE --gnu --add-missing || exit 1 48 | 49 | echo "autoconf..." 50 | AUTOCONF=${AUTOCONF:-autoconf} 51 | $AUTOCONF || exit 1 52 | 53 | -------------------------------------------------------------------------------- /memcached-sr/bipbuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef BIPBUFFER_H 2 | #define BIPBUFFER_H 3 | 4 | typedef struct 5 | { 6 | unsigned long int size; 7 | 8 | /* region A */ 9 | unsigned int a_start, a_end; 10 | 11 | /* region B */ 12 | unsigned int b_end; 13 | 14 | /* is B inuse? */ 15 | int b_inuse; 16 | 17 | unsigned char data[]; 18 | } bipbuf_t; 19 | 20 | /** 21 | * Create a new bip buffer. 22 | * 23 | * malloc()s space 24 | * 25 | * @param[in] size The size of the buffer */ 26 | bipbuf_t *bipbuf_new(const unsigned int size); 27 | 28 | /** 29 | * Initialise a bip buffer. Use memory provided by user. 30 | * 31 | * No malloc()s are performed. 32 | * 33 | * @param[in] size The size of the array */ 34 | void bipbuf_init(bipbuf_t* me, const unsigned int size); 35 | 36 | /** 37 | * Free the bip buffer */ 38 | void bipbuf_free(bipbuf_t *me); 39 | 40 | /* TODO: DOCUMENTATION */ 41 | unsigned char *bipbuf_request(bipbuf_t* me, const int size); 42 | int bipbuf_push(bipbuf_t* me, const int size); 43 | 44 | /** 45 | * @param[in] data The data to be offered to the buffer 46 | * @param[in] size The size of the data to be offered 47 | * @return number of bytes offered */ 48 | int bipbuf_offer(bipbuf_t *me, const unsigned char *data, const int size); 49 | 50 | /** 51 | * Look at data. Don't move cursor 52 | * 53 | * @param[in] len The length of the data to be peeked 54 | * @return data on success, NULL if we can't peek at this much data */ 55 | unsigned char *bipbuf_peek(const bipbuf_t* me, const unsigned int len); 56 | 57 | /** 58 | * Look at data. Don't move cursor 59 | * 60 | * @param[in] len The length of the data returned 61 | * @return data on success, NULL if nothing available */ 62 | unsigned char *bipbuf_peek_all(const bipbuf_t* me, unsigned int *len); 63 | 64 | /** 65 | * Get pointer to data to read. Move the cursor on. 66 | * 67 | * @param[in] len The length of the data to be polled 68 | * @return pointer to data, NULL if we can't poll this much data */ 69 | unsigned char *bipbuf_poll(bipbuf_t* me, const unsigned int size); 70 | 71 | /** 72 | * @return the size of the bipbuffer */ 73 | int bipbuf_size(const bipbuf_t* me); 74 | 75 | /** 76 | * @return 1 if buffer is empty; 0 otherwise */ 77 | int bipbuf_is_empty(const bipbuf_t* me); 78 | 79 | /** 80 | * @return how much space we have assigned */ 81 | int bipbuf_used(const bipbuf_t* cb); 82 | 83 | /** 84 | * @return bytes of unused space */ 85 | int bipbuf_unused(const bipbuf_t* me); 86 | 87 | #endif /* BIPBUFFER_H */ 88 | -------------------------------------------------------------------------------- /memcached-sr/crawler.h: -------------------------------------------------------------------------------- 1 | #ifndef CRAWLER_H 2 | #define CRAWLER_H 3 | 4 | #define LRU_CRAWLER_CAP_REMAINING -1 5 | 6 | typedef struct { 7 | uint64_t histo[61]; 8 | uint64_t ttl_hourplus; 9 | uint64_t noexp; 10 | uint64_t reclaimed; 11 | uint64_t seen; 12 | rel_time_t start_time; 13 | rel_time_t end_time; 14 | bool run_complete; 15 | } crawlerstats_t; 16 | 17 | struct crawler_expired_data { 18 | pthread_mutex_t lock; 19 | crawlerstats_t crawlerstats[POWER_LARGEST]; 20 | /* redundant with crawlerstats_t so we can get overall start/stop/done */ 21 | rel_time_t start_time; 22 | rel_time_t end_time; 23 | bool crawl_complete; 24 | bool is_external; /* whether this was an alloc local or remote to the module. */ 25 | }; 26 | 27 | enum crawler_result_type { 28 | CRAWLER_OK=0, CRAWLER_RUNNING, CRAWLER_BADCLASS, CRAWLER_NOTSTARTED, CRAWLER_ERROR 29 | }; 30 | int start_item_crawler_thread(void); 31 | #define CRAWLER_WAIT true 32 | #define CRAWLER_NOWAIT false 33 | int stop_item_crawler_thread(bool wait); 34 | int init_lru_crawler(void *arg); 35 | enum crawler_result_type lru_crawler_crawl(char *slabs, enum crawler_run_type, 36 | void *c, const int sfd, unsigned int remaining); 37 | int lru_crawler_start(uint8_t *ids, uint32_t remaining, 38 | const enum crawler_run_type type, void *data, 39 | void *c, const int sfd); 40 | void lru_crawler_pause(void); 41 | void lru_crawler_resume(void); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /memcached-sr/crc32c.h: -------------------------------------------------------------------------------- 1 | #ifndef CRC32C_H 2 | #define CRC32C_H 3 | 4 | typedef uint32_t (*crc_func)(uint32_t crc, const void *buf, size_t len); 5 | crc_func crc32c; 6 | 7 | void crc32c_init(void); 8 | 9 | #endif /* CRC32C_H */ 10 | -------------------------------------------------------------------------------- /memcached-sr/daemon.c: -------------------------------------------------------------------------------- 1 | /* $Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $ */ 2 | /* $NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $ */ 3 | /*- 4 | * Copyright (c) 1990, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | */ 31 | 32 | #if defined __SUNPRO_C || defined __DECC || defined __HP_cc 33 | # pragma ident "@(#)$Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $" 34 | # pragma ident "$NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $" 35 | #endif 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "memcached.h" 43 | 44 | int daemonize(int nochdir, int noclose) 45 | { 46 | int fd; 47 | 48 | switch (fork()) { 49 | case -1: 50 | return (-1); 51 | case 0: 52 | break; 53 | default: 54 | _exit(EXIT_SUCCESS); 55 | } 56 | 57 | if (setsid() == -1) 58 | return (-1); 59 | 60 | if (nochdir == 0) { 61 | if(chdir("/") != 0) { 62 | perror("chdir"); 63 | return (-1); 64 | } 65 | } 66 | 67 | if (noclose == 0 && (fd = open("/dev/null", O_RDWR, 0)) != -1) { 68 | if(dup2(fd, STDIN_FILENO) < 0) { 69 | perror("dup2 stdin"); 70 | return (-1); 71 | } 72 | if(dup2(fd, STDOUT_FILENO) < 0) { 73 | perror("dup2 stdout"); 74 | return (-1); 75 | } 76 | if(dup2(fd, STDERR_FILENO) < 0) { 77 | perror("dup2 stderr"); 78 | return (-1); 79 | } 80 | 81 | if (fd > STDERR_FILENO) { 82 | if(close(fd) < 0) { 83 | perror("close"); 84 | return (-1); 85 | } 86 | } 87 | } 88 | return (0); 89 | } 90 | -------------------------------------------------------------------------------- /memcached-sr/devtools/Dockerfile.alpine: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | 3 | RUN apk update && apk add --no-cache musl-dev libevent-dev libseccomp-dev linux-headers gcc make automake autoconf perl-test-harness-utils 4 | 5 | ADD . /src 6 | WORKDIR /src 7 | 8 | RUN ./autogen.sh 9 | RUN ./configure --enable-seccomp 10 | RUN make -j 11 | 12 | CMD make test 13 | -------------------------------------------------------------------------------- /memcached-sr/devtools/Dockerfile.arch: -------------------------------------------------------------------------------- 1 | FROM archlinux/base:latest 2 | 3 | RUN pacman -Sy && pacman --noconfirm -S gcc automake autoconf libevent libseccomp git make perl 4 | RUN ln -s /usr/bin/core_perl/prove /usr/bin/prove 5 | 6 | ADD . /src 7 | WORKDIR /src 8 | 9 | RUN aclocal 10 | RUN autoheader 11 | RUN automake --gnu --add-missing 12 | RUN autoconf 13 | 14 | RUN ./configure --enable-seccomp 15 | RUN make -j 16 | 17 | CMD make test 18 | -------------------------------------------------------------------------------- /memcached-sr/devtools/Dockerfile.fedora: -------------------------------------------------------------------------------- 1 | FROM fedora:latest 2 | 3 | RUN dnf install -y perl automake autoconf libseccomp-devel libevent-devel gcc make git 4 | 5 | ADD . /src 6 | WORKDIR /src 7 | 8 | RUN aclocal && autoheader && automake --foreign --add-missing && autoconf 9 | RUN ./configure --enable-seccomp 10 | RUN make -j 11 | 12 | CMD make test 13 | -------------------------------------------------------------------------------- /memcached-sr/devtools/Dockerfile.ubuntu: -------------------------------------------------------------------------------- 1 | FROM ubuntu:latest 2 | 3 | RUN apt-get update && apt-get install -y build-essential automake1.11 autoconf libevent-dev libseccomp-dev git 4 | 5 | ADD . /src 6 | WORKDIR /src 7 | 8 | RUN ./autogen.sh 9 | RUN ./configure --enable-seccomp 10 | RUN make -j 11 | 12 | CMD make test 13 | -------------------------------------------------------------------------------- /memcached-sr/devtools/bench_noreply.pl: -------------------------------------------------------------------------------- 1 | #! /usr/bin/perl 2 | # 3 | use warnings; 4 | use strict; 5 | 6 | use IO::Socket::INET; 7 | 8 | use FindBin; 9 | 10 | @ARGV == 1 or @ARGV == 2 11 | or die "Usage: $FindBin::Script HOST:PORT [COUNT]\n"; 12 | 13 | # Note that it's better to run the test over the wire, because for 14 | # localhost the task may become CPU bound. 15 | my $addr = $ARGV[0]; 16 | my $count = $ARGV[1] || 10_000; 17 | 18 | my $sock = IO::Socket::INET->new(PeerAddr => $addr, 19 | Timeout => 3); 20 | die "$!\n" unless $sock; 21 | 22 | 23 | # By running 'noreply' test first we also ensure there are no reply 24 | # packets left in the network. 25 | foreach my $noreply (1, 0) { 26 | use Time::HiRes qw(gettimeofday tv_interval); 27 | 28 | print "'noreply' is ", $noreply ? "enabled" : "disabled", ":\n"; 29 | my $param = $noreply ? 'noreply' : ''; 30 | my $start = [gettimeofday]; 31 | foreach (1 .. $count) { 32 | print $sock "add foo 0 0 1 $param\r\n1\r\n"; 33 | scalar<$sock> unless $noreply; 34 | print $sock "set foo 0 0 1 $param\r\n1\r\n"; 35 | scalar<$sock> unless $noreply; 36 | print $sock "replace foo 0 0 1 $param\r\n1\r\n"; 37 | scalar<$sock> unless $noreply; 38 | print $sock "append foo 0 0 1 $param\r\n1\r\n"; 39 | scalar<$sock> unless $noreply; 40 | print $sock "prepend foo 0 0 1 $param\r\n1\r\n"; 41 | scalar<$sock> unless $noreply; 42 | print $sock "incr foo 1 $param\r\n"; 43 | scalar<$sock> unless $noreply; 44 | print $sock "decr foo 1 $param\r\n"; 45 | scalar<$sock> unless $noreply; 46 | print $sock "delete foo $param\r\n"; 47 | scalar<$sock> unless $noreply; 48 | } 49 | my $end = [gettimeofday]; 50 | printf("update commands: %.2f secs\n\n", tv_interval($start, $end)); 51 | } 52 | -------------------------------------------------------------------------------- /memcached-sr/devtools/clean-whitespace.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | use strict; 3 | use FindBin qw($Bin); 4 | chdir "$Bin/.." or die; 5 | 6 | my @exempted = qw(Makefile.am ChangeLog doc/Makefile.am README README.md); 7 | push(@exempted, glob("doc/*.xml")); 8 | push(@exempted, glob("doc/*.full")); 9 | push(@exempted, glob("doc/xml2rfc/*.xsl")); 10 | push(@exempted, glob("m4/*backport*m4")); 11 | my %exempted_hash = map { $_ => 1 } @exempted; 12 | 13 | my @stuff = split /\0/, `git ls-files -z -c -m -o --exclude-standard`; 14 | my @files = grep { ! $exempted_hash{$_} } @stuff; 15 | 16 | unless (@files) { 17 | warn "ERROR: You don't seem to be running this from a git checkout\n"; 18 | exit; 19 | } 20 | 21 | foreach my $f (@files) { 22 | open(my $fh, $f) or die; 23 | my $before = do { local $/; <$fh>; }; 24 | close ($fh); 25 | my $after = $before; 26 | $after =~ s/\t/ /g; 27 | $after =~ s/ +$//mg; 28 | $after .= "\n" unless $after =~ /\n$/; 29 | next if $after eq $before; 30 | open(my $fh, ">$f") or die; 31 | print $fh $after; 32 | close($fh); 33 | } 34 | -------------------------------------------------------------------------------- /memcached-sr/devtools/slab_loadgen: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # Copyright 2017 Facebook 3 | # Licensed under the same terms as memcached itself. 4 | 5 | import argparse 6 | import socket 7 | import csv 8 | from time import sleep 9 | 10 | parser = argparse.ArgumentParser(description="daemon for emulating set/get pressure") 11 | parser.add_argument("--host", help="host to connect to", 12 | type=str, default="localhost:11211") 13 | parser.add_argument("-s", "--sleep", help="seconds between rounds", 14 | type=int, default="1") 15 | parser.add_argument("-c", "--config", help="load specification file", 16 | type=str, default="./config") 17 | 18 | args = parser.parse_args() 19 | 20 | # prefix, size, count, do_gets 21 | with open(args.config, newline='') as f: 22 | reader = csv.reader(f) 23 | tests = [row for row in reader] 24 | 25 | host, port = args.host.split(':') 26 | 27 | c = socket.create_connection((host, port), 5) 28 | s = c.makefile(mode="rw", buffering=1) 29 | 30 | global_counter = 0 31 | 32 | while True: 33 | # LATER: stat argument file 34 | # LATER: reload arg file if necessary 35 | for test in tests: 36 | prefix = test[0] 37 | size = int(test[1]) 38 | count = int(test[2]) 39 | do_gets = int(test[3]) 40 | value = 'x'*size 41 | # issue N 'noreply' sets per specified size 42 | for i in range(count): 43 | s.write('set {}{} 0 0 {} noreply\r\n{}\r\n'.format(prefix,global_counter,size,value)) 44 | global_counter += 1 45 | # TODO: issue N gets per specified size? 46 | sleep(args.sleep) 47 | -------------------------------------------------------------------------------- /memcached-sr/doc/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | MEMCACHED CONTRIBUTORS 2 | 3 | This file contains a list of people who have contributed code and 4 | effort to the memcached project. If you don't see your name mentioned 5 | send email to the memcached mailing list so you can be immortalized. 6 | 7 | Also see the ChangeLog for even more people who have helped over the 8 | years by submitting fixes, patches and reporting bugs. 9 | 10 | A list is generated from git here: https://memcached.org/about 11 | 12 | Major authors: 13 | -------------- 14 | 15 | Brad Fitzpatrick -- maintainer, original implementations 16 | 17 | Anatoly Vorobey -- lots of the modern server code 18 | 19 | Steven Grimm -- iov writing (less CPU), UDP mode, 20 | non-2.0 slab mantissas, multithread, ... 21 | 22 | Other Contributors 23 | ------------------ 24 | 25 | Evan Martin 26 | Nathan Neulinger 27 | Eric Hodel 28 | Michael Johnson 29 | Paul Querna 30 | Jamie McCarthy 31 | Philip Neustrom 32 | Andrew O'Brien 33 | Josh Rotenberg 34 | Robin H. Johnson 35 | Tim Yardley 36 | Paolo Borelli 37 | Eli Bingham 38 | Jean-Francois Bustarret 39 | Paul G 40 | Paul Lindner 41 | Dormando 42 | Dustin Sallings 43 | Chris Goffinet 44 | Tomash Brechko 45 | Brian Aker 46 | Trond Norbye 47 | -------------------------------------------------------------------------------- /memcached-sr/doc/Makefile.am: -------------------------------------------------------------------------------- 1 | man_MANS = memcached.1 2 | 3 | EXTRA_DIST = *.txt 4 | 5 | BUILT_SOURCES= 6 | 7 | if BUILD_SPECIFICATIONS 8 | BUILT_SOURCES += protocol-binary.txt protocol-binary-range.txt 9 | MOSTLYCLEANFILES = protocol-binary.txt protocol-binary-range.txt 10 | endif 11 | 12 | protocol-binary.txt: protocol-binary.full 13 | @XML2RFC@ -c @abs_builddir@ protocol-binary.full $@ 14 | 15 | protocol-binary-range.txt: protocol-binary-range.full 16 | @XML2RFC@ -c @abs_builddir@ protocol-binary-range.full $@ 17 | 18 | protocol-binary.full: protocol-binary.xml xml2rfc/rfc2629-noinc.xsl 19 | @XSLTPROC@ --nonet xml2rfc/rfc2629-noinc.xsl protocol-binary.xml > $@ 20 | 21 | protocol-binary-range.full: protocol-binary-range.xml xml2rfc/rfc2629-noinc.xsl 22 | @XSLTPROC@ --nonet xml2rfc/rfc2629-noinc.xsl protocol-binary-range.xml > $@ 23 | 24 | -------------------------------------------------------------------------------- /memcached-sr/doc/new_lru.txt: -------------------------------------------------------------------------------- 1 | In versions new enough to have the `-o lru_maintainer` option, a new LRU 2 | mechanic is available. 3 | 4 | Previously: Each slab class has an independent doubly-linked list comprising 5 | its LRU. Items are pulled from the bottom and either reclaimed or evicted as 6 | needed. 7 | 8 | Now, enabling `-o lru_maintainer` changes all of the behavior below: 9 | 10 | * LRU's are now split between HOT, WARM, and COLD LRU's. New items enter the 11 | HOT LRU. 12 | * Items hit at least twice are considered active. 13 | * LRU updates only happen as items reach the bottom of an LRU. If active in 14 | HOT, move to WARM, if active in WARM, stay in WARM. If active in COLD, move 15 | to WARM. 16 | The exception is that items active in COLD are immediately moved to WARM. 17 | * HOT/WARM each capped at N% of memory available for that slab class. COLD 18 | is uncapped (by default, as of this writing). 19 | * HOT/WARM are also age capped by ratios of COLD's age. IE: HOT is capped at 20 | N% of memory, or 10% of the age of COLD, whichever comes first. 21 | * Items flow from HOT/WARM into COLD. 22 | * A background thread exists which shuffles items between/within the LRU's as 23 | limits are reached. This includes moves from COLD to WARM. 24 | * The background thread can also control the lru_crawler, if enabled. 25 | 26 | The primary goal is to better protect active items from "scanning". Items 27 | which are never hit again will flow from HOT, through COLD, and out the 28 | bottom. Items occasionally active (reaching COLD, but being hit before 29 | eviction), move to WARM. There they can stay relatively protected. 30 | 31 | A secondary goal is to improve latency. The LRU locks are no longer used on 32 | most item reads, largely during sets and from the background thread. Also the 33 | background thread is likely to find expired items and release them back to the 34 | slab class asynchronously, which speeds up new allocations. 35 | 36 | It is recommended to use this feature with the lru crawler as well: 37 | `memcached -o lru_maintainer,lru_crawler` - Then it will automatically scan 38 | slab classes for items with expired TTL's. If your items are always set to 39 | never expire, you can omit this option safely. 40 | 41 | An extra option: `-o temporary_ttl=N` (when used with lru_maintainer) will make 42 | items with a TTL less than or equal to this value use a fourth TEMP LRU. Items 43 | stored in TEMP are never bumped within its LRU or moved to other LRU's. They 44 | also cannot be evicted. This can help reduce holes and load on the LRU crawler. 45 | 46 | Do not set temporary_ttl too high or memory could become exhausted. 47 | -------------------------------------------------------------------------------- /memcached-sr/doc/readme.txt: -------------------------------------------------------------------------------- 1 | To build the documentation you need xml2rfc ( http://xml.resource.org/ ). 2 | -------------------------------------------------------------------------------- /memcached-sr/doc/threads.txt: -------------------------------------------------------------------------------- 1 | Multithreading in memcached *was* originally simple: 2 | 3 | - One listener thread 4 | - N "event worker" threads 5 | - Some misc background threads 6 | 7 | Each worker thread is assigned connections, and runs its own epoll loop. The 8 | central hash table, LRU lists, and some statistics counters are covered by 9 | global locks. Protocol parsing, data transfer happens in threads. Data lookups 10 | and modifications happen under central locks. 11 | 12 | THIS HAS CHANGED! 13 | 14 | - A secondary small hash table of locks is used to lock an item by its hash 15 | value. This prevents multiple threads from acting on the same item at the 16 | same time. 17 | - This secondary hash table is mapped to the central hash tables buckets. This 18 | allows multiple threads to access the hash table in parallel. Only one 19 | thread may read or write against a particular hash table bucket. 20 | - atomic refcounts per item are used to manage garbage collection and 21 | mutability. 22 | 23 | - When pulling an item off of the LRU tail for eviction or re-allocation, the 24 | system must attempt to lock the item's bucket, which is done with a trylock 25 | to avoid deadlocks. If a bucket is in use (and not by that thread) it will 26 | walk up the LRU a little in an attempt to fetch a non-busy item. 27 | 28 | - Each LRU (and sub-LRU's in newer modes) has an independent lock. 29 | 30 | - Raw accesses to the slab class are protected by a global slabs_lock. This 31 | is a short lock which covers pushing and popping free memory. 32 | 33 | - item_lock must be held while modifying an item. 34 | - slabs_lock must be held while modifying the ITEM_SLABBED flag bit within an item. 35 | - ITEM_LINKED must not be set before an item has a key copied into it. 36 | - items without ITEM_SLABBED set cannot have their memory zeroed out. 37 | 38 | LOCK ORDERS: 39 | 40 | (incomplete as of writing, sorry): 41 | 42 | item_lock -> lru_lock -> slabs_lock 43 | 44 | lru_lock -> item_trylock 45 | 46 | Various stats_locks should never have other locks as dependencies. 47 | 48 | Various locks exist for background threads. They can be used to pause the 49 | thread execution or update settings while the threads are idle. They may call 50 | item or lru locks. 51 | 52 | A low priority issue: 53 | 54 | - If you remove the per-thread stats lock, CPU usage goes down by less than a 55 | point of a percent, and it does not improve scalability. 56 | - In my testing, the remaining global STATS_LOCK calls never seem to collide. 57 | 58 | Yes, more stats can be moved to threads, and those locks can actually be 59 | removed entirely on x86-64 systems. However my tests haven't shown that as 60 | beneficial so far, so I've prioritized other work. 61 | -------------------------------------------------------------------------------- /memcached-sr/doc/xml2rfc/reference.RFC.0768.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | User Datagram Protocol 7 | 8 | University of Southern California (USC)/Information Sciences Institute 9 |
10 | 11 | 4676 Admiralty Way 12 | Marina del Rey 13 | CA 14 | 90291 15 | US 16 | +1 213 822 1511
17 |
18 | 19 | 20 | 21 | 22 |
23 | -------------------------------------------------------------------------------- /memcached-sr/doc/xml2rfc/reference.RFC.2119.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Key words for use in RFCs to Indicate Requirement Levels 7 | 8 | Harvard University 9 |
10 | 11 | 1350 Mass. Ave. 12 | Cambridge 13 | MA 02138 14 | - +1 617 495 3864 15 | sob@harvard.edu
16 | 17 | General 18 | keyword 19 | 20 | 21 | In many standards track documents several words are used to signify 22 | the requirements in the specification. These words are often 23 | capitalized. This document defines these words as they should be 24 | interpreted in IETF documents. Authors who follow these guidelines 25 | should incorporate this phrase near the beginning of their document: 26 | 27 | 28 | 29 | The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL 30 | NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and 31 | "OPTIONAL" in this document are to be interpreted as described in 32 | RFC 2119. 33 | 34 | 35 | Note that the force of these words is modified by the requirement 36 | level of the document in which they are used. 37 |
38 | 39 | 40 | 41 | 42 | 43 | 44 |
45 | -------------------------------------------------------------------------------- /memcached-sr/doc/xml2rfc/rfc2629-noinc.xsl: -------------------------------------------------------------------------------- 1 | 2 | 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 | .xml 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 | 101 | 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /memcached-sr/doc/xml2rfc/rfc2629-other.ent: -------------------------------------------------------------------------------- 1 | 20 | 21 | 22 | 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 | -------------------------------------------------------------------------------- /memcached-sr/doc/xml2rfc/rfc2629-refchk.xsl: -------------------------------------------------------------------------------- 1 | 2 | 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 | -------------------------------------------------------------------------------- /memcached-sr/docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | services: 3 | alpine: 4 | build: 5 | context: . 6 | dockerfile: devtools/Dockerfile.alpine 7 | ubuntu: 8 | build: 9 | context: . 10 | dockerfile: devtools/Dockerfile.ubuntu 11 | arch: 12 | build: 13 | context: . 14 | dockerfile: devtools/Dockerfile.arch 15 | fedora: 16 | build: 17 | context: . 18 | dockerfile: devtools/Dockerfile.fedora 19 | -------------------------------------------------------------------------------- /memcached-sr/freebsd_priv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "memcached.h" 8 | 9 | /* 10 | * dropping privileges is entering in capability mode 11 | * in FreeBSD vocabulary. 12 | */ 13 | void drop_privileges() { 14 | cap_rights_t wd, rd; 15 | 16 | if (cap_rights_init(&wd, CAP_WRITE, CAP_READ) == NULL) { 17 | fprintf(stderr, "cap_rights_init write protection failed: %s\n", strerror(errno)); 18 | exit(EXIT_FAILURE); 19 | } 20 | 21 | if (cap_rights_init(&rd, CAP_FCNTL, CAP_READ, CAP_EVENT) == NULL) { 22 | fprintf(stderr, "cap_rights_init read protection failed: %s\n", strerror(errno)); 23 | exit(EXIT_FAILURE); 24 | } 25 | 26 | if (cap_rights_limit(STDIN_FILENO, &rd) != 0) { 27 | fprintf(stderr, "cap_rights_limit stdin failed: %s\n", strerror(errno)); 28 | exit(EXIT_FAILURE); 29 | } 30 | 31 | if (cap_rights_limit(STDOUT_FILENO, &wd) != 0) { 32 | fprintf(stderr, "cap_rights_limit stdout failed: %s\n", strerror(errno)); 33 | exit(EXIT_FAILURE); 34 | } 35 | 36 | if (cap_rights_limit(STDERR_FILENO, &wd) != 0) { 37 | fprintf(stderr, "cap_rights_limit stderr failed: %s\n", strerror(errno)); 38 | exit(EXIT_FAILURE); 39 | } 40 | 41 | if (cap_enter() != 0) { 42 | fprintf(stderr, "cap_enter failed: %s\n", strerror(errno)); 43 | exit(EXIT_FAILURE); 44 | } 45 | } 46 | 47 | void setup_privilege_violations_handler(void) { 48 | // not needed 49 | } 50 | -------------------------------------------------------------------------------- /memcached-sr/globals.c: -------------------------------------------------------------------------------- 1 | #include "memcached.h" 2 | 3 | /* 4 | * This file contains global variables shared across the rest of the 5 | * memcached codebase. These were originally in memcached.c but had 6 | * to be removed to make the rest of the object files linkable into 7 | * the test infrastructure. 8 | * 9 | */ 10 | 11 | /* 12 | * We keep the current time of day in a global variable that's updated by a 13 | * timer event. This saves us a bunch of time() system calls (we really only 14 | * need to get the time once a second, whereas there can be tens of thousands 15 | * of requests a second) and allows us to use server-start-relative timestamps 16 | * rather than absolute UNIX timestamps, a space savings on systems where 17 | * sizeof(time_t) > sizeof(unsigned int). 18 | */ 19 | volatile rel_time_t current_time; 20 | 21 | /** exported globals **/ 22 | struct stats stats; 23 | struct stats_state stats_state; 24 | struct settings settings; 25 | struct slab_rebalance slab_rebal; 26 | volatile int slab_rebalance_signal; 27 | -------------------------------------------------------------------------------- /memcached-sr/hash.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | 3 | #include "memcached.h" 4 | #include "jenkins_hash.h" 5 | #include "murmur3_hash.h" 6 | 7 | int hash_init(enum hashfunc_type type) { 8 | switch(type) { 9 | case JENKINS_HASH: 10 | hash = jenkins_hash; 11 | settings.hash_algorithm = "jenkins"; 12 | break; 13 | case MURMUR3_HASH: 14 | hash = MurmurHash3_x86_32; 15 | settings.hash_algorithm = "murmur3"; 16 | break; 17 | default: 18 | return -1; 19 | } 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /memcached-sr/hash.h: -------------------------------------------------------------------------------- 1 | #ifndef HASH_H 2 | #define HASH_H 3 | 4 | typedef uint32_t (*hash_func)(const void *key, size_t length); 5 | hash_func hash; 6 | 7 | enum hashfunc_type { 8 | JENKINS_HASH=0, MURMUR3_HASH 9 | }; 10 | 11 | int hash_init(enum hashfunc_type type); 12 | 13 | #endif /* HASH_H */ 14 | 15 | -------------------------------------------------------------------------------- /memcached-sr/items.h: -------------------------------------------------------------------------------- 1 | #define HOT_LRU 0 2 | #define WARM_LRU 64 3 | #define COLD_LRU 128 4 | #define TEMP_LRU 192 5 | 6 | #define CLEAR_LRU(id) (id & ~(3<<6)) 7 | #define GET_LRU(id) (id & (3<<6)) 8 | 9 | /* See items.c */ 10 | uint64_t get_cas_id(void); 11 | void set_cas_id(uint64_t new_cas); 12 | 13 | /*@null@*/ 14 | item *do_item_alloc(char *key, const size_t nkey, const unsigned int flags, const rel_time_t exptime, const int nbytes); 15 | item_chunk *do_item_alloc_chunk(item_chunk *ch, const size_t bytes_remain); 16 | item *do_item_alloc_pull(const size_t ntotal, const unsigned int id); 17 | void item_free(item *it); 18 | bool item_size_ok(const size_t nkey, const int flags, const int nbytes); 19 | 20 | int do_item_link(item *it, const uint32_t hv); /** may fail if transgresses limits */ 21 | void do_item_unlink(item *it, const uint32_t hv); 22 | void do_item_unlink_nolock(item *it, const uint32_t hv); 23 | void do_item_remove(item *it); 24 | void do_item_update(item *it); /** update LRU time to current and reposition */ 25 | void do_item_update_nolock(item *it); 26 | int do_item_replace(item *it, item *new_it, const uint32_t hv); 27 | void do_item_link_fixup(item *it); 28 | 29 | int item_is_flushed(item *it); 30 | unsigned int do_get_lru_size(uint32_t id); 31 | 32 | void do_item_linktail_q(item *it); 33 | void do_item_unlinktail_q(item *it); 34 | item *do_item_crawl_q(item *it); 35 | 36 | void *item_lru_bump_buf_create(void); 37 | 38 | #define LRU_PULL_EVICT 1 39 | #define LRU_PULL_CRAWL_BLOCKS 2 40 | #define LRU_PULL_RETURN_ITEM 4 /* fill info struct if available */ 41 | 42 | struct lru_pull_tail_return { 43 | item *it; 44 | uint32_t hv; 45 | }; 46 | 47 | int lru_pull_tail(const int orig_id, const int cur_lru, 48 | const uint64_t total_bytes, const uint8_t flags, const rel_time_t max_age, 49 | struct lru_pull_tail_return *ret_it); 50 | 51 | /*@null@*/ 52 | char *item_cachedump(const unsigned int slabs_clsid, const unsigned int limit, unsigned int *bytes); 53 | void item_stats(ADD_STAT add_stats, void *c); 54 | void do_item_stats_add_crawl(const int i, const uint64_t reclaimed, 55 | const uint64_t unfetched, const uint64_t checked); 56 | void item_stats_totals(ADD_STAT add_stats, void *c); 57 | /*@null@*/ 58 | void item_stats_sizes(ADD_STAT add_stats, void *c); 59 | void item_stats_sizes_init(void); 60 | void item_stats_sizes_enable(ADD_STAT add_stats, void *c); 61 | void item_stats_sizes_disable(ADD_STAT add_stats, void *c); 62 | void item_stats_sizes_add(item *it); 63 | void item_stats_sizes_remove(item *it); 64 | bool item_stats_sizes_status(void); 65 | 66 | /* stats getter for slab automover */ 67 | typedef struct { 68 | int64_t evicted; 69 | int64_t outofmemory; 70 | uint32_t age; 71 | } item_stats_automove; 72 | void fill_item_stats_automove(item_stats_automove *am); 73 | 74 | item *do_item_get(const char *key, const size_t nkey, const uint32_t hv, conn *c, const bool do_update); 75 | item *do_item_touch(const char *key, const size_t nkey, uint32_t exptime, const uint32_t hv, conn *c); 76 | void do_item_bump(conn *c, item *it, const uint32_t hv); 77 | void item_stats_reset(void); 78 | extern pthread_mutex_t lru_locks[POWER_LARGEST]; 79 | 80 | int start_lru_maintainer_thread(void *arg); 81 | int stop_lru_maintainer_thread(void); 82 | int init_lru_maintainer(void); 83 | void lru_maintainer_pause(void); 84 | void lru_maintainer_resume(void); 85 | 86 | void *lru_bump_buf_create(void); 87 | 88 | #ifdef EXTSTORE 89 | #define STORAGE_delete(e, it) \ 90 | do { \ 91 | if (it->it_flags & ITEM_HDR) { \ 92 | item_hdr *hdr = (item_hdr *)ITEM_data(it); \ 93 | extstore_delete(e, hdr->page_id, hdr->page_version, \ 94 | 1, ITEM_ntotal(it)); \ 95 | } \ 96 | } while (0) 97 | #else 98 | #define STORAGE_delete(...) 99 | #endif 100 | -------------------------------------------------------------------------------- /memcached-sr/itoa_ljust.h: -------------------------------------------------------------------------------- 1 | #ifndef ITOA_LJUST_H 2 | #define ITOA_LJUST_H 3 | 4 | //=== itoa_ljust.h - Fast integer to ascii conversion 5 | // 6 | // Fast and simple integer to ASCII conversion: 7 | // 8 | // - 32 and 64-bit integers 9 | // - signed and unsigned 10 | // - user supplied buffer must be large enough for all decimal digits 11 | // in value plus minus sign if negative 12 | // - left-justified 13 | // - NUL terminated 14 | // - return value is pointer to NUL terminator 15 | // 16 | // Copyright (c) 2016 Arturo Martin-de-Nicolas 17 | // arturomdn@gmail.com 18 | // https://github.com/amdn/itoa_ljust/ 19 | //===----------------------------------------------------------------------===// 20 | 21 | #include 22 | 23 | char* itoa_u32(uint32_t u, char* buffer); 24 | char* itoa_32( int32_t i, char* buffer); 25 | char* itoa_u64(uint64_t u, char* buffer); 26 | char* itoa_64( int64_t i, char* buffer); 27 | 28 | #endif // ITOA_LJUST_H 29 | -------------------------------------------------------------------------------- /memcached-sr/jenkins_hash.h: -------------------------------------------------------------------------------- 1 | #ifndef JENKINS_HASH_H 2 | #define JENKINS_HASH_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | uint32_t jenkins_hash(const void *key, size_t length); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif /* JENKINS_HASH_H */ 15 | 16 | -------------------------------------------------------------------------------- /memcached-sr/murmur3_hash.c: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // MurmurHash3 was written by Austin Appleby, and is placed in the public 3 | // domain. The author hereby disclaims copyright to this source code. 4 | 5 | // Note - The x86 and x64 versions do _not_ produce the same results, as the 6 | // algorithms are optimized for their respective platforms. You can still 7 | // compile and run any of them on any platform, but your performance with the 8 | // non-native version will be less than optimal. 9 | 10 | #include "murmur3_hash.h" 11 | 12 | //----------------------------------------------------------------------------- 13 | // Platform-specific functions and macros 14 | 15 | // Microsoft Visual Studio 16 | 17 | #if defined(_MSC_VER) 18 | 19 | #define FORCE_INLINE __forceinline 20 | 21 | #include 22 | 23 | #define ROTL32(x,y) _rotl(x,y) 24 | 25 | #define BIG_CONSTANT(x) (x) 26 | 27 | // Other compilers 28 | 29 | #else // defined(_MSC_VER) 30 | 31 | #define FORCE_INLINE inline __attribute__((always_inline)) 32 | 33 | static inline uint32_t rotl32 ( uint32_t x, int8_t r ) 34 | { 35 | return (x << r) | (x >> (32 - r)); 36 | } 37 | 38 | #define ROTL32(x,y) rotl32(x,y) 39 | 40 | #define BIG_CONSTANT(x) (x##LLU) 41 | 42 | #endif // !defined(_MSC_VER) 43 | 44 | //----------------------------------------------------------------------------- 45 | // Block read - if your platform needs to do endian-swapping or can only 46 | // handle aligned reads, do the conversion here 47 | 48 | static FORCE_INLINE uint32_t getblock32 ( const uint32_t * p, int i ) 49 | { 50 | return p[i]; 51 | } 52 | 53 | //----------------------------------------------------------------------------- 54 | // Finalization mix - force all bits of a hash block to avalanche 55 | 56 | static FORCE_INLINE uint32_t fmix32 ( uint32_t h ) 57 | { 58 | h ^= h >> 16; 59 | h *= 0x85ebca6b; 60 | h ^= h >> 13; 61 | h *= 0xc2b2ae35; 62 | h ^= h >> 16; 63 | 64 | return h; 65 | } 66 | 67 | //----------------------------------------------------------------------------- 68 | 69 | /* Definition modified slightly from the public domain interface (no seed + 70 | * return value */ 71 | uint32_t MurmurHash3_x86_32 ( const void * key, size_t length) 72 | { 73 | const uint8_t * data = (const uint8_t*)key; 74 | const int nblocks = length / 4; 75 | 76 | uint32_t h1 = 0; 77 | 78 | uint32_t c1 = 0xcc9e2d51; 79 | uint32_t c2 = 0x1b873593; 80 | 81 | //---------- 82 | // body 83 | 84 | const uint32_t * blocks = (const uint32_t *)(data + nblocks*4); 85 | 86 | for(int i = -nblocks; i; i++) 87 | { 88 | uint32_t k1 = getblock32(blocks,i); 89 | 90 | k1 *= c1; 91 | k1 = ROTL32(k1,15); 92 | k1 *= c2; 93 | 94 | h1 ^= k1; 95 | h1 = ROTL32(h1,13); 96 | h1 = h1*5+0xe6546b64; 97 | } 98 | 99 | //---------- 100 | // tail 101 | 102 | const uint8_t * tail = (const uint8_t*)(data + nblocks*4); 103 | 104 | uint32_t k1 = 0; 105 | 106 | switch(length & 3) 107 | { 108 | case 3: k1 ^= tail[2] << 16; 109 | case 2: k1 ^= tail[1] << 8; 110 | case 1: k1 ^= tail[0]; 111 | k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1; 112 | }; 113 | 114 | //---------- 115 | // finalization 116 | 117 | h1 ^= length; 118 | 119 | h1 = fmix32(h1); 120 | 121 | //*(uint32_t*)out = h1; 122 | return h1; 123 | } 124 | 125 | -------------------------------------------------------------------------------- /memcached-sr/murmur3_hash.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // MurmurHash3 was written by Austin Appleby, and is placed in the public 3 | // domain. The author hereby disclaims copyright to this source code. 4 | 5 | #ifndef MURMURHASH3_H 6 | #define MURMURHASH3_H 7 | 8 | //----------------------------------------------------------------------------- 9 | // Platform-specific functions and macros 10 | #include 11 | #include 12 | 13 | //----------------------------------------------------------------------------- 14 | 15 | uint32_t MurmurHash3_x86_32(const void *key, size_t length); 16 | 17 | //----------------------------------------------------------------------------- 18 | 19 | #endif // MURMURHASH3_H 20 | -------------------------------------------------------------------------------- /memcached-sr/openbsd_priv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "memcached.h" 7 | 8 | /* 9 | * this section of code will drop all (OpenBSD) privileges including 10 | * those normally granted to all userland process (basic privileges). The 11 | * effect of this is that after running this code, the process will not able 12 | * to fork(), exec(), etc. See pledge(2) for more information. 13 | */ 14 | void drop_privileges() { 15 | extern char *__progname; 16 | 17 | if (settings.socketpath != NULL) { 18 | if (pledge("stdio unix", NULL) == -1) { 19 | fprintf(stderr, "%s: pledge: %s\n", __progname, strerror(errno)); 20 | exit(EXIT_FAILURE); 21 | } 22 | } else { 23 | if (pledge("stdio inet", NULL) == -1) { 24 | fprintf(stderr, "%s: pledge: %s\n", __progname, strerror(errno)); 25 | exit(EXIT_FAILURE); 26 | } 27 | } 28 | } 29 | 30 | void setup_privilege_violations_handler(void) { 31 | // not needed 32 | } 33 | -------------------------------------------------------------------------------- /memcached-sr/restart.h: -------------------------------------------------------------------------------- 1 | #ifndef RESTART_H 2 | #define RESTART_H 3 | 4 | #define RESTART_TAG_MAXLEN 255 5 | 6 | // Track the pointer size for restart fiddling. 7 | #ifdef HAVE_64BIT_PTR 8 | typedef uint64_t mc_ptr_t; 9 | #else 10 | typedef uint32_t mc_ptr_t; 11 | #endif 12 | 13 | enum restart_get_kv_ret { 14 | RESTART_OK=0, RESTART_NOTAG, RESTART_BADLINE, RESTART_DONE 15 | }; 16 | 17 | typedef int (*restart_check_cb)(const char *tag, void *ctx, void *data); 18 | typedef int (*restart_save_cb)(const char *tag, void *ctx, void *data); 19 | void restart_register(const char *tag, restart_check_cb ccb, restart_save_cb scb, void *data); 20 | 21 | void restart_set_kv(void *ctx, const char *key, const char *fmt, ...); 22 | enum restart_get_kv_ret restart_get_kv(void *ctx, char **key, char **val); 23 | 24 | bool restart_mmap_open(const size_t limit, const char *file, void **mem_base); 25 | void restart_mmap_close(void); 26 | void restart_mmap_set(void); 27 | unsigned int restart_fixup(void *old_base); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /memcached-sr/sasl_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef SASL_DEFS_H 2 | #define SASL_DEFS_H 1 3 | 4 | // Longest one I could find was ``9798-U-RSA-SHA1-ENC'' 5 | #define MAX_SASL_MECH_LEN 32 6 | 7 | #if defined(HAVE_SASL_SASL_H) && defined(ENABLE_SASL) 8 | 9 | #include 10 | void init_sasl(void); 11 | 12 | extern char my_sasl_hostname[1025]; 13 | 14 | #else /* End of SASL support */ 15 | 16 | typedef void* sasl_conn_t; 17 | 18 | #define init_sasl() {} 19 | #define sasl_dispose(x) {} 20 | #define sasl_server_new(a, b, c, d, e, f, g, h) 1 21 | #define sasl_listmech(a, b, c, d, e, f, g, h) 1 22 | #define sasl_server_start(a, b, c, d, e, f) 1 23 | #define sasl_server_step(a, b, c, d, e) 1 24 | #define sasl_getprop(a, b, c) {} 25 | 26 | #define SASL_OK 0 27 | #define SASL_CONTINUE -1 28 | 29 | #endif /* sasl compat */ 30 | 31 | #endif /* SASL_DEFS_H */ 32 | -------------------------------------------------------------------------------- /memcached-sr/scripts/README.damemtop: -------------------------------------------------------------------------------- 1 | dormando's awesome memcached top 2 | 3 | A flexible 'top' like utility for viewing memcached clusters. 4 | 5 | Under development. Latest code is available at: 6 | http://github.com/dormando/damemtop 7 | 8 | See --help for full information. 9 | 10 | Requires 'AnyEvent', and 'YAML' libraries from CPAN: 11 | http://search.cpan.org/ 12 | 13 | 'AnyEvent' depends on 'common::sense' (also at CPAN). 14 | 15 | If you have a large cluster and want higher performance, find 16 | and install 'EV' from CPAN. AnyEvent will automagically use it 17 | and use epoll, kqeueue, etc, for socket handling. 18 | 19 | Pester me for questions/bugs/ideas. As of writing the util is 20 | in early release and missing many future features. 21 | -------------------------------------------------------------------------------- /memcached-sr/scripts/damemtop.yaml: -------------------------------------------------------------------------------- 1 | delay: 3 2 | mode: t 3 | top_mode: 4 | sort_column: "hostname" 5 | sort_order: "asc" 6 | columns: 7 | - hostname 8 | - all_version 9 | - all_fill_rate 10 | - hit_rate 11 | - evictions 12 | - bytes_written 13 | - "2:get_hits" 14 | servers: 15 | - 127.0.0.1:11211 16 | - 127.0.0.2:11211 17 | -------------------------------------------------------------------------------- /memcached-sr/scripts/memcached-init: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | ### BEGIN INIT INFO 3 | # Provides: memcached 4 | # Required-Start: $syslog 5 | # Required-Stop: $syslog 6 | # Should-Start: $local_fs 7 | # Should-Stop: $local_fs 8 | # Default-Start: 2 3 4 5 9 | # Default-Stop: 0 1 6 10 | # Short-Description: memcached - Memory caching daemon 11 | # Description: memcached - Memory caching daemon 12 | ### END INIT INFO 13 | 14 | # Usage: 15 | # cp /etc/memcached.conf /etc/memcached_server1.conf 16 | # cp /etc/memcached.conf /etc/memcached_server2.conf 17 | # start all instances: 18 | # /etc/init.d/memcached start 19 | # start one instance: 20 | # /etc/init.d/memcached start server1 21 | # stop all instances: 22 | # /etc/init.d/memcached stop 23 | # stop one instance: 24 | # /etc/init.d/memcached stop server1 25 | # There is no "status" command. 26 | 27 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 28 | DAEMON=/usr/bin/memcached 29 | DAEMONNAME=memcached 30 | DAEMONBOOTSTRAP=/usr/share/memcached/scripts/start-memcached 31 | DESC=memcached 32 | 33 | test -x $DAEMON || exit 0 34 | test -x $DAEMONBOOTSTRAP || exit 0 35 | 36 | set -e 37 | 38 | FILES=(/etc/memcached_*.conf) 39 | # check for alternative config schema 40 | if [ -r "${FILES[0]}" ]; then 41 | CONFIGS=() 42 | for FILE in "${FILES[@]}"; 43 | do 44 | # remove prefix 45 | NAME=${FILE#/etc/} 46 | # remove suffix 47 | NAME=${NAME%.conf} 48 | 49 | # check optional second param 50 | if [ $# -ne 2 ]; 51 | then 52 | # add to config array 53 | CONFIGS+=($NAME) 54 | elif [ "memcached_$2" == "$NAME" ]; 55 | then 56 | # use only one memcached 57 | CONFIGS=($NAME) 58 | break; 59 | fi; 60 | done; 61 | 62 | if [ ${#CONFIGS[@]} == 0 ]; 63 | then 64 | echo "Config not exist for: $2" >&2 65 | exit 1 66 | fi; 67 | else 68 | CONFIGS=(memcached) 69 | fi; 70 | 71 | CONFIG_NUM=${#CONFIGS[@]} 72 | for ((i=0; i < $CONFIG_NUM; i++)); do 73 | NAME=${CONFIGS[${i}]} 74 | PIDFILE="/var/run/${NAME}.pid" 75 | 76 | case "$1" in 77 | start) 78 | echo -n "Starting $DESC: " 79 | start-stop-daemon --start --quiet --exec "$DAEMONBOOTSTRAP" -- /etc/${NAME}.conf $PIDFILE 80 | echo "$NAME." 81 | ;; 82 | stop) 83 | echo -n "Stopping $DESC: " 84 | start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON 85 | echo "$NAME." 86 | rm -f $PIDFILE 87 | ;; 88 | status) 89 | [ $# -lt 2 ] && NAME=$DAEMONNAME 90 | PIDFILE="/var/run/$NAME.pid" 91 | set +e 92 | start-stop-daemon --status --pidfile $PIDFILE 93 | case $? in 94 | 0) echo "$DESC: $NAME (pid $(cat $PIDFILE)) is running" && exit 0;; 95 | 1) echo "$DESC: $NAME is not running thro' the pid file exists" && rm -f $PIDFILE && exit 1;; 96 | 3) echo "$DESC: $NAME is not running" && exit 3;; 97 | 4) echo "$DESC: $NAME status is unclear, sorry" && exit 4;; 98 | esac 99 | ;; 100 | restart|force-reload) 101 | # 102 | # If the "reload" option is implemented, move the "force-reload" 103 | # option to the "reload" entry above. If not, "force-reload" is 104 | # just the same as "restart". 105 | # 106 | echo -n "Restarting $DESC: " 107 | start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE 108 | rm -f $PIDFILE 109 | sleep 1 110 | start-stop-daemon --start --quiet --exec "$DAEMONBOOTSTRAP" -- /etc/${NAME}.conf $PIDFILE 111 | echo "$NAME." 112 | ;; 113 | *) 114 | N=/etc/init.d/$NAME 115 | # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2 116 | echo "Usage: $N {start|stop|status|restart|force-reload}" >&2 117 | exit 1 118 | ;; 119 | esac 120 | done; 121 | 122 | exit 0 123 | -------------------------------------------------------------------------------- /memcached-sr/scripts/memcached-server.upstart: -------------------------------------------------------------------------------- 1 | description "memcached-server - high-performance memory caching daemon (instance)" 2 | author "Cameron Norman " 3 | 4 | stop on stop-memcached-servers or runlevel [016] 5 | 6 | expect daemon 7 | respawn 8 | 9 | # Instance w/ default value so main server starts without SERVER param 10 | env SERVER="" 11 | instance $SERVER 12 | usage "SERVER - instance of memcached with corresponding /etc/memcached_$SERVER config" 13 | 14 | script 15 | if test "x$SERVER" = "x"; then 16 | name="memcached" 17 | else 18 | name="memcached_$SERVER" 19 | fi 20 | 21 | test -f /etc/${name}.conf || { 22 | echo "No config found, not starting."; exit 1 23 | } 24 | 25 | exec /usr/share/memcached/scripts/start-memcached /etc/${name}.conf /var/run/${name}.pid 26 | end script 27 | -------------------------------------------------------------------------------- /memcached-sr/scripts/memcached-tool.1: -------------------------------------------------------------------------------- 1 | .TH MEMCACHED-TOOL 1 "Jul 2, 2013" 2 | .SH NAME 3 | memcached-tool \- stats and management tool for memcached 4 | 5 | .SH SYNOPSIS 6 | .B memcached-tool 7 | .RI < host [: port "] | " /path/to/socket "> [" mode ] 8 | 9 | .SH DESCRIPTION 10 | .B memcached-tool 11 | is a Perl script used to print statistics from a running memcached instance. 12 | The first parameter specifies the address of the daemon either by a hostname, 13 | optionally followed by the port number (the default is 11211), or a path to 14 | UNIX domain socket. The second parameter specifies the mode in which the tool 15 | should run. 16 | 17 | .SH MODES 18 | .TP 19 | .B display 20 | Print slab class statistics. This is the default mode if no mode is specified. 21 | The printed columns are: 22 | .RS 23 | .TP 24 | .B # 25 | Number of the slab class. 26 | .TP 27 | .B Item_Size 28 | The amount of space each chunk uses. One item uses one chunk of the 29 | appropriate size. 30 | .TP 31 | .B Max_age 32 | Age of the oldest item in the LRU. 33 | .TP 34 | .B Pages 35 | Total number of pages allocated to the slab class. 36 | .TP 37 | .B Count 38 | Number of items presently stored in this class. Expired items are not 39 | automatically excluded. 40 | .TP 41 | .B Full? 42 | Yes if there are no free chunks at the end of the last allocated page. 43 | .TP 44 | .B Evicted 45 | Number of times an item had to be evicted from the LRU before it expired. 46 | .TP 47 | .B Evict_Time 48 | Seconds since the last access for the most recent item evicted from this 49 | class. 50 | .TP 51 | .B OOM 52 | Number of times the underlying slab class was unable to store a new item. 53 | .RE 54 | 55 | .TP 56 | .B stats 57 | Print general-purpose statistics of the daemon. Each line contains the name of 58 | the statistic and its value. 59 | .TP 60 | .B dump [limit] 61 | Make a partial dump of the cache written in the add statements of the 62 | memcached protocol. If 63 | .B limit 64 | is given and is a strictly positive 65 | integer, then the dump is limited to that number of items. 66 | 67 | .SH SEE ALSO 68 | .BR memcached (1), 69 | .br 70 | .B https://www.memcached.org 71 | 72 | .SH AUTHOR 73 | The memcached-tool script was written by Brad Fitzpatrick 74 | .B 75 | -------------------------------------------------------------------------------- /memcached-sr/scripts/memcached.service: -------------------------------------------------------------------------------- 1 | # It's not recommended to modify this file in-place, because it will be 2 | # overwritten during upgrades. If you want to customize, the best 3 | # way is to use the "systemctl edit" command to create an override unit. 4 | # 5 | # For example, to pass additional options, create an override unit 6 | # (as is done by systemctl edit) and enter the following: 7 | # 8 | # [Service] 9 | # Environment=OPTIONS="-l 127.0.0.1,::1" 10 | 11 | 12 | [Unit] 13 | Description=memcached daemon 14 | After=network.target 15 | 16 | [Service] 17 | EnvironmentFile=/etc/sysconfig/memcached 18 | ExecStart=/usr/bin/memcached -p ${PORT} -u ${USER} -m ${CACHESIZE} -c ${MAXCONN} $OPTIONS 19 | 20 | # Set up a new file system namespace and mounts private /tmp and /var/tmp 21 | # directories so this service cannot access the global directories and 22 | # other processes cannot access this service's directories. 23 | PrivateTmp=true 24 | 25 | # Mounts the /usr, /boot, and /etc directories read-only for processes 26 | # invoked by this unit. 27 | ProtectSystem=full 28 | 29 | # Ensures that the service process and all its children can never gain new 30 | # privileges 31 | NoNewPrivileges=true 32 | 33 | # Sets up a new /dev namespace for the executed processes and only adds API 34 | # pseudo devices such as /dev/null, /dev/zero or /dev/random (as well as 35 | # the pseudo TTY subsystem) to it, but no physical devices such as /dev/sda. 36 | PrivateDevices=true 37 | 38 | # Required for dropping privileges and running as a different user 39 | CapabilityBoundingSet=CAP_SETGID CAP_SETUID CAP_SYS_RESOURCE 40 | 41 | # Restricts the set of socket address families accessible to the processes 42 | # of this unit. Protects against vulnerabilities such as CVE-2016-8655 43 | RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX 44 | 45 | 46 | # Some security features are not in the older versions of systemd used by 47 | # e.g. RHEL7/CentOS 7. The below settings are automatically edited at package 48 | # build time to uncomment them if the target platform supports them. 49 | 50 | # Attempts to create memory mappings that are writable and executable at 51 | # the same time, or to change existing memory mappings to become executable 52 | # are prohibited. 53 | ##safer##MemoryDenyWriteExecute=true 54 | 55 | # Explicit module loading will be denied. This allows to turn off module 56 | # load and unload operations on modular kernels. It is recommended to turn 57 | # this on for most services that do not need special file systems or extra 58 | # kernel modules to work. 59 | ##safer##ProtectKernelModules=true 60 | 61 | # Kernel variables accessible through /proc/sys, /sys, /proc/sysrq-trigger, 62 | # /proc/latency_stats, /proc/acpi, /proc/timer_stats, /proc/fs and /proc/irq 63 | # will be made read-only to all processes of the unit. Usually, tunable 64 | # kernel variables should only be written at boot-time, with the sysctl.d(5) 65 | # mechanism. Almost no services need to write to these at runtime; it is hence 66 | # recommended to turn this on for most services. 67 | ##safer##ProtectKernelTunables=true 68 | 69 | # The Linux Control Groups (cgroups(7)) hierarchies accessible through 70 | # /sys/fs/cgroup will be made read-only to all processes of the unit. 71 | # Except for container managers no services should require write access 72 | # to the control groups hierarchies; it is hence recommended to turn this 73 | # on for most services 74 | ##safer##ProtectControlGroups=true 75 | 76 | # Any attempts to enable realtime scheduling in a process of the unit are 77 | # refused. 78 | ##safer##RestrictRealtime=true 79 | 80 | # Takes away the ability to create or manage any kind of namespace 81 | ##safer##RestrictNamespaces=true 82 | 83 | [Install] 84 | WantedBy=multi-user.target 85 | -------------------------------------------------------------------------------- /memcached-sr/scripts/memcached.sysconfig: -------------------------------------------------------------------------------- 1 | # These defaults will be used by every memcached instance, unless overridden 2 | # by values in /etc/sysconfig/memcached. 3 | USER="nobody" 4 | MAXCONN="1024" 5 | CACHESIZE="64" 6 | OPTIONS="" 7 | 8 | # The PORT variable will only be used by memcached.service, not by 9 | # memcached@xxxxx services, which will use the xxxxx 10 | PORT="11211" 11 | -------------------------------------------------------------------------------- /memcached-sr/scripts/memcached.sysv: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # chkconfig: - 55 45 4 | # description: The memcached daemon is a network memory cache service. 5 | # processname: memcached 6 | # config: /etc/sysconfig/memcached 7 | 8 | # Source function library. 9 | . /etc/rc.d/init.d/functions 10 | 11 | PORT=11211 12 | USER=nobody 13 | MAXCONN=1024 14 | CACHESIZE=64 15 | OPTIONS="" 16 | 17 | if [ -f /etc/sysconfig/memcached ];then 18 | . /etc/sysconfig/memcached 19 | fi 20 | 21 | # Check that networking is up. 22 | if [ "$NETWORKING" = "no" ] 23 | then 24 | exit 0 25 | fi 26 | 27 | RETVAL=0 28 | prog="memcached" 29 | 30 | start () { 31 | echo -n $"Starting $prog: " 32 | # insure that /var/run/memcached has proper permissions 33 | chown $USER /var/run/memcached 34 | daemon memcached -d -p $PORT -u $USER -m $CACHESIZE -c $MAXCONN -P /var/run/memcached/memcached.pid $OPTIONS 35 | RETVAL=$? 36 | echo 37 | [ $RETVAL -eq 0 ] && touch /var/lock/subsys/memcached 38 | } 39 | stop () { 40 | echo -n $"Stopping $prog: " 41 | killproc memcached 42 | RETVAL=$? 43 | echo 44 | if [ $RETVAL -eq 0 ] ; then 45 | rm -f /var/lock/subsys/memcached 46 | rm -f /var/run/memcached/memcached.pid 47 | fi 48 | } 49 | 50 | restart () { 51 | stop 52 | start 53 | } 54 | 55 | 56 | # See how we were called. 57 | case "$1" in 58 | start) 59 | start 60 | ;; 61 | stop) 62 | stop 63 | ;; 64 | status) 65 | status memcached 66 | ;; 67 | restart|reload) 68 | restart 69 | ;; 70 | condrestart) 71 | [ -f /var/lock/subsys/memcached ] && restart || : 72 | ;; 73 | *) 74 | echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}" 75 | exit 1 76 | esac 77 | 78 | exit $? 79 | -------------------------------------------------------------------------------- /memcached-sr/scripts/memcached.upstart: -------------------------------------------------------------------------------- 1 | description "memcached - high performance memory caching daemon" 2 | author "Cameron Norman " 3 | 4 | start on filesystem 5 | stop on runlevel [016] 6 | 7 | pre-start script 8 | ret=0 9 | 10 | test -x /usr/bin/memcached || { stop; exit 0; } 11 | 12 | # Main 13 | start memcached-server || ret=$? 14 | # Instances 15 | for i in /etc/memcached_*.conf; do 16 | i=${i#/etc/memcached_} 17 | i=${i%.conf} 18 | test "$i" = "*" && continue 19 | start memcached-server SERVER=$i || ret=$? 20 | done 21 | 22 | exit $ret 23 | end script 24 | 25 | post-stop exec initctl emit stop-memcached-servers 26 | -------------------------------------------------------------------------------- /memcached-sr/scripts/start-memcached: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | 3 | # start-memcached 4 | # 2003/2004 - Jay Bonci 5 | # This script handles the parsing of the /etc/memcached.conf file 6 | # and was originally created for the Debian distribution. 7 | # Anyone may use this little script under the same terms as 8 | # memcached itself. 9 | 10 | use POSIX qw(setsid); 11 | use strict; 12 | 13 | if($> != 0 and $< != 0) 14 | { 15 | print STDERR "Only root wants to run start-memcached.\n"; 16 | exit; 17 | } 18 | 19 | my $params; my $etchandle; my $etcfile = "/etc/memcached.conf"; 20 | 21 | # This script assumes that memcached is located at /usr/bin/memcached, and 22 | # that the pidfile is writable at /var/run/memcached.pid 23 | 24 | my $memcached = "/usr/bin/memcached"; 25 | my $pidfile = "/var/run/memcached.pid"; 26 | 27 | if (scalar(@ARGV) == 2) { 28 | $etcfile = shift(@ARGV); 29 | $pidfile = shift(@ARGV); 30 | } 31 | 32 | # If we don't get a valid logfile parameter in the /etc/memcached.conf file, 33 | # we'll just throw away all of our in-daemon output. We need to re-tie it so 34 | # that non-bash shells will not hang on logout. Thanks to Michael Renner for 35 | # the tip 36 | my $fd_reopened = "/dev/null"; 37 | 38 | sub handle_logfile 39 | { 40 | my ($logfile) = @_; 41 | $fd_reopened = $logfile; 42 | } 43 | 44 | sub reopen_logfile 45 | { 46 | my ($logfile) = @_; 47 | 48 | open *STDERR, ">>$logfile"; 49 | open *STDOUT, ">>$logfile"; 50 | open *STDIN, ">>/dev/null"; 51 | $fd_reopened = $logfile; 52 | } 53 | 54 | # This is set up in place here to support other non -[a-z] directives 55 | 56 | my $conf_directives = { 57 | "logfile" => \&handle_logfile, 58 | }; 59 | 60 | if(open $etchandle, $etcfile) 61 | { 62 | foreach my $line (<$etchandle>) 63 | { 64 | $line ||= ""; 65 | $line =~ s/(?{$directive}->($arg); 75 | next; 76 | } 77 | 78 | push @$params, $line; 79 | } 80 | 81 | }else{ 82 | $params = []; 83 | } 84 | 85 | push @$params, "-u root" unless(grep "-u", @$params); 86 | $params = join " ", @$params; 87 | 88 | if(-e $pidfile) 89 | { 90 | open PIDHANDLE, "$pidfile"; 91 | my $localpid = ; 92 | close PIDHANDLE; 93 | 94 | chomp $localpid; 95 | if(-d "/proc/$localpid") 96 | { 97 | print STDERR "memcached is already running.\n"; 98 | exit; 99 | }else{ 100 | unlink $pidfile; 101 | } 102 | 103 | } 104 | 105 | my $pid = fork(); 106 | 107 | if($pid == 0) 108 | { 109 | # setsid makes us the session leader 110 | setsid(); 111 | reopen_logfile($fd_reopened); 112 | # must fork again now that tty is closed 113 | $pid = fork(); 114 | if ($pid) { 115 | if(open PIDHANDLE,">$pidfile") 116 | { 117 | print PIDHANDLE $pid; 118 | close PIDHANDLE; 119 | }else{ 120 | 121 | print STDERR "Can't write pidfile to $pidfile.\n"; 122 | } 123 | exit(0); 124 | } 125 | exec "$memcached $params"; 126 | exit(0); 127 | 128 | } 129 | -------------------------------------------------------------------------------- /memcached-sr/sizes.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "memcached.h" 4 | 5 | static void display(const char *name, size_t size) { 6 | printf("%s\t%d\n", name, (int)size); 7 | } 8 | 9 | int main(int argc, char **argv) { 10 | 11 | display("Slab Stats", sizeof(struct slab_stats)); 12 | display("Thread stats", 13 | sizeof(struct thread_stats) 14 | - (200 * sizeof(struct slab_stats))); 15 | display("Global stats", sizeof(struct stats)); 16 | display("Settings", sizeof(struct settings)); 17 | display("Item (no cas)", sizeof(item)); 18 | display("Item (cas)", sizeof(item) + sizeof(uint64_t)); 19 | #ifdef EXTSTORE 20 | display("extstore header", sizeof(item_hdr)); 21 | #endif 22 | display("Libevent thread", 23 | sizeof(LIBEVENT_THREAD) - sizeof(struct thread_stats)); 24 | display("Connection", sizeof(conn)); 25 | 26 | printf("----------------------------------------\n"); 27 | 28 | display("libevent thread cumulative", sizeof(LIBEVENT_THREAD)); 29 | display("Thread stats cumulative\t", sizeof(struct thread_stats)); 30 | 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /memcached-sr/slab_automove.h: -------------------------------------------------------------------------------- 1 | #ifndef SLAB_AUTOMOVE_H 2 | #define SLAB_AUTOMOVE_H 3 | 4 | /* default automove functions */ 5 | void *slab_automove_init(struct settings *settings); 6 | void slab_automove_free(void *arg); 7 | void slab_automove_run(void *arg, int *src, int *dst); 8 | 9 | typedef void *(*slab_automove_init_func)(struct settings *settings); 10 | typedef void (*slab_automove_free_func)(void *arg); 11 | typedef void (*slab_automove_run_func)(void *arg, int *src, int *dst); 12 | 13 | typedef struct { 14 | slab_automove_init_func init; 15 | slab_automove_free_func free; 16 | slab_automove_run_func run; 17 | } slab_automove_reg_t; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /memcached-sr/slab_automove_extstore.h: -------------------------------------------------------------------------------- 1 | #ifndef SLAB_AUTOMOVE_EXTSTORE_H 2 | #define SLAB_AUTOMOVE_EXTSTORE_H 3 | 4 | void *slab_automove_extstore_init(struct settings *settings); 5 | void slab_automove_extstore_free(void *arg); 6 | void slab_automove_extstore_run(void *arg, int *src, int *dst); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /memcached-sr/slabs.h: -------------------------------------------------------------------------------- 1 | /* slabs memory allocation */ 2 | #ifndef SLABS_H 3 | #define SLABS_H 4 | 5 | /** Init the subsystem. 1st argument is the limit on no. of bytes to allocate, 6 | 0 if no limit. 2nd argument is the growth factor; each slab will use a chunk 7 | size equal to the previous slab's chunk size times this factor. 8 | 3rd argument specifies if the slab allocator should allocate all memory 9 | up front (if true), or allocate memory in chunks as it is needed (if false) 10 | */ 11 | void slabs_init(const size_t limit, const double factor, const bool prealloc, const uint32_t *slab_sizes, void *mem_base_external, bool reuse_mem); 12 | 13 | /** Call only during init. Pre-allocates all available memory */ 14 | void slabs_prefill_global(void); 15 | 16 | /** 17 | * Given object size, return id to use when allocating/freeing memory for object 18 | * 0 means error: can't store such a large object 19 | */ 20 | 21 | unsigned int slabs_clsid(const size_t size); 22 | unsigned int slabs_size(const int clsid); 23 | 24 | /** Allocate object of given length. 0 on error */ /*@null@*/ 25 | #define SLABS_ALLOC_NO_NEWPAGE 1 26 | void *slabs_alloc(const size_t size, unsigned int id, unsigned int flags); 27 | 28 | /** Free previously allocated object */ 29 | void slabs_free(void *ptr, size_t size, unsigned int id); 30 | 31 | /** Adjust global memory limit up or down */ 32 | bool slabs_adjust_mem_limit(size_t new_mem_limit); 33 | 34 | typedef struct { 35 | unsigned int chunks_per_page; 36 | unsigned int chunk_size; 37 | long int free_chunks; 38 | long int total_pages; 39 | } slab_stats_automove; 40 | void fill_slab_stats_automove(slab_stats_automove *am); 41 | unsigned int global_page_pool_size(bool *mem_flag); 42 | 43 | /** Fill buffer with stats */ /*@null@*/ 44 | void slabs_stats(ADD_STAT add_stats, void *c); 45 | 46 | /* Hints as to freespace in slab class */ 47 | unsigned int slabs_available_chunks(unsigned int id, bool *mem_flag, unsigned int *chunks_perslab); 48 | 49 | void slabs_mlock(void); 50 | void slabs_munlock(void); 51 | 52 | int start_slab_maintenance_thread(void); 53 | void stop_slab_maintenance_thread(void); 54 | 55 | enum reassign_result_type { 56 | REASSIGN_OK=0, REASSIGN_RUNNING, REASSIGN_BADCLASS, REASSIGN_NOSPARE, 57 | REASSIGN_SRC_DST_SAME 58 | }; 59 | 60 | enum reassign_result_type slabs_reassign(int src, int dst); 61 | 62 | void slabs_rebalancer_pause(void); 63 | void slabs_rebalancer_resume(void); 64 | 65 | #ifdef EXTSTORE 66 | void slabs_set_storage(void *arg); 67 | #endif 68 | 69 | /* Fixup for restartable code. */ 70 | unsigned int slabs_fixup(char *chunk, const int border); 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /memcached-sr/solaris_priv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "memcached.h" 5 | 6 | /* 7 | * this section of code will drop all (Solaris) privileges including 8 | * those normally granted to all userland process (basic privileges). The 9 | * effect of this is that after running this code, the process will not able 10 | * to fork(), exec(), etc. See privileges(5) for more information. 11 | */ 12 | void drop_privileges(void) { 13 | priv_set_t *privs = priv_str_to_set("basic", ",", NULL); 14 | 15 | if (privs == NULL) { 16 | perror("priv_str_to_set"); 17 | exit(EXIT_FAILURE); 18 | } 19 | 20 | (void)priv_delset(privs, PRIV_FILE_LINK_ANY); 21 | (void)priv_delset(privs, PRIV_PROC_EXEC); 22 | (void)priv_delset(privs, PRIV_PROC_FORK); 23 | (void)priv_delset(privs, PRIV_PROC_INFO); 24 | (void)priv_delset(privs, PRIV_PROC_SESSION); 25 | 26 | if (setppriv(PRIV_SET, PRIV_PERMITTED, privs) != 0) { 27 | perror("setppriv(PRIV_SET, PRIV_PERMITTED)"); 28 | exit(EXIT_FAILURE); 29 | } 30 | 31 | priv_emptyset(privs); 32 | 33 | if (setppriv(PRIV_SET, PRIV_INHERITABLE, privs) != 0) { 34 | perror("setppriv(PRIV_SET, PRIV_INHERITABLE)"); 35 | exit(EXIT_FAILURE); 36 | } 37 | 38 | if (setppriv(PRIV_SET, PRIV_LIMIT, privs) != 0) { 39 | perror("setppriv(PRIV_SET, PRIV_LIMIT)"); 40 | exit(EXIT_FAILURE); 41 | } 42 | 43 | priv_freeset(privs); 44 | } 45 | 46 | void setup_privilege_violations_handler(void) { 47 | // not needed 48 | } 49 | -------------------------------------------------------------------------------- /memcached-sr/stats.h: -------------------------------------------------------------------------------- 1 | /* stats */ 2 | void stats_prefix_init(void); 3 | void stats_prefix_clear(void); 4 | void stats_prefix_record_get(const char *key, const size_t nkey, const bool is_hit); 5 | void stats_prefix_record_delete(const char *key, const size_t nkey); 6 | void stats_prefix_record_set(const char *key, const size_t nkey); 7 | /*@null@*/ 8 | char *stats_prefix_dump(int *length); 9 | -------------------------------------------------------------------------------- /memcached-sr/storage.h: -------------------------------------------------------------------------------- 1 | #ifndef STORAGE_H 2 | #define STORAGE_H 3 | 4 | int start_storage_write_thread(void *arg); 5 | void storage_write_pause(void); 6 | void storage_write_resume(void); 7 | int start_storage_compact_thread(void *arg); 8 | void storage_compact_pause(void); 9 | void storage_compact_resume(void); 10 | struct extstore_conf_file *storage_conf_parse(char *arg, unsigned int page_size); 11 | 12 | // Ignore pointers and header bits from the CRC 13 | #define STORE_OFFSET offsetof(item, nbytes) 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /memcached-sr/t/00-startup.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 20; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | eval { 10 | my $server = new_memcached(); 11 | ok($server, "started the server"); 12 | }; 13 | is($@, '', 'Basic startup works'); 14 | 15 | eval { 16 | my $server = new_memcached("-l fooble"); 17 | }; 18 | ok($@, "Died with illegal -l args"); 19 | 20 | eval { 21 | my $server = new_memcached("-l 127.0.0.1"); 22 | }; 23 | is($@,'', "-l 127.0.0.1 works"); 24 | 25 | eval { 26 | my $server = new_memcached('-C'); 27 | my $stats = mem_stats($server->sock, 'settings'); 28 | is('no', $stats->{'cas_enabled'}); 29 | }; 30 | is($@, '', "-C works"); 31 | 32 | eval { 33 | my $server = new_memcached('-b 8675'); 34 | my $stats = mem_stats($server->sock, 'settings'); 35 | is('8675', $stats->{'tcp_backlog'}); 36 | }; 37 | is($@, '', "-b works"); 38 | 39 | foreach my $val ('auto', 'ascii') { 40 | eval { 41 | my $server = new_memcached("-B $val"); 42 | my $stats = mem_stats($server->sock, 'settings'); 43 | ok($stats->{'binding_protocol'} =~ /$val/, "$val works"); 44 | }; 45 | is($@, '', "$val works"); 46 | } 47 | 48 | # For the binary test, we just verify it starts since we don't have an easy bin client. 49 | eval { 50 | my $server = new_memcached("-B binary"); 51 | }; 52 | is($@, '', "binary works"); 53 | 54 | eval { 55 | my $server = new_memcached("-vv -B auto"); 56 | }; 57 | is($@, '', "auto works"); 58 | 59 | eval { 60 | my $server = new_memcached("-vv -B ascii"); 61 | }; 62 | is($@, '', "ascii works"); 63 | 64 | 65 | # For the binary test, we just verify it starts since we don't have an easy bin client. 66 | eval { 67 | my $server = new_memcached("-vv -B binary"); 68 | }; 69 | is($@, '', "binary works"); 70 | 71 | 72 | # Should blow up with something invalid. 73 | eval { 74 | my $server = new_memcached("-B http"); 75 | }; 76 | ok($@, "Died with illegal -B arg."); 77 | 78 | # Maximum connections must be greater than 0. 79 | eval { 80 | my $server = new_memcached("-c 0"); 81 | }; 82 | ok($@, "Died with invalid maximum connections 0."); 83 | eval { 84 | my $server = new_memcached("-c -1"); 85 | }; 86 | ok($@, "Died with invalid maximum connections -1."); 87 | 88 | # Should not allow -t 0 89 | eval { 90 | my $server = new_memcached("-t 0"); 91 | }; 92 | ok($@, "Died with illegal 0 thread count"); 93 | -------------------------------------------------------------------------------- /memcached-sr/t/64bit.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | $ENV{T_MEMD_INITIAL_MALLOC} = "4294967328"; # 2**32 + 32 , just over 4GB 10 | $ENV{T_MEMD_SLABS_ALLOC} = 0; # don't preallocate slabs 11 | 12 | my $server = new_memcached("-m 4098 -M"); 13 | my $sock = $server->sock; 14 | 15 | my ($stats, $slabs) = @_; 16 | 17 | $stats = mem_stats($sock); 18 | 19 | if ($stats->{'pointer_size'} eq "32") { 20 | plan skip_all => 'Skipping 64-bit tests on 32-bit build'; 21 | exit 0; 22 | } else { 23 | plan tests => 6; 24 | } 25 | 26 | is($stats->{'pointer_size'}, 64, "is 64 bit"); 27 | is($stats->{'limit_maxbytes'}, "4297064448", "max bytes is 4098 MB"); 28 | 29 | $slabs = mem_stats($sock, 'slabs'); 30 | is($slabs->{'total_malloced'}, "4294967328", "expected (faked) value of total_malloced"); 31 | is($slabs->{'active_slabs'}, 0, "no active slabs"); 32 | 33 | my $hit_limit = 0; 34 | for (1..5) { 35 | my $size = 400 * 1024; 36 | my $data = "a" x $size; 37 | print $sock "set big$_ 0 0 $size\r\n$data\r\n"; 38 | my $res = <$sock>; 39 | $hit_limit = 1 if $res ne "STORED\r\n"; 40 | } 41 | ok($hit_limit, "hit size limit"); 42 | 43 | $slabs = mem_stats($sock, 'slabs'); 44 | is($slabs->{'active_slabs'}, 1, "1 active slab"); 45 | -------------------------------------------------------------------------------- /memcached-sr/t/ascii-auth.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 9; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | # FIXME: Some tests are forcing UDP to be enabled via MemcachedTest.pm - need 10 | # to audit and fix. 11 | my $server = new_memcached("-Y $Bin/authfile -U 0"); 12 | my $sock = $server->sock; 13 | 14 | # Test unauthenticated modes 15 | print $sock "set foo 0 0 2\r\nhi\r\n"; 16 | like(scalar <$sock>, qr/CLIENT_ERROR/, "failed to do a write"); 17 | print $sock "get foo\r\n"; 18 | like(scalar <$sock>, qr/CLIENT_ERROR/, "failed to do a read"); 19 | 20 | # Fail to authenticate. 21 | print $sock "set foo 0 0 7\r\nfoo bab\r\n"; 22 | like(scalar <$sock>, qr/CLIENT_ERROR/, "failed to authenticate"); 23 | 24 | # Try for real. 25 | print $sock "set foo 0 0 7\r\nfoo bar\r\n"; 26 | like(scalar <$sock>, qr/STORED/, "authenticated?"); 27 | 28 | print $sock "set toast 0 0 2\r\nhi\r\n"; 29 | like(scalar <$sock>, qr/STORED/, "stored an item that didn't look like user/pass"); 30 | 31 | mem_get_is($sock, "toast", "hi"); 32 | 33 | # Create a second socket, try to authenticate against the second token. 34 | 35 | my $sock2 = $server->new_sock; 36 | 37 | print $sock2 "set foo 0 0 10\r\nbaaaz quux\r\n"; 38 | like(scalar <$sock2>, qr/STORED/, "authenticated a second socket?"); 39 | 40 | print $sock2 "set toast2 0 0 2\r\nho\r\n"; 41 | like(scalar <$sock2>, qr/STORED/, "stored an item that didn't look like user/pass"); 42 | 43 | mem_get_is($sock2, "toast2", "ho"); 44 | 45 | # TODO: tests for reloads. 46 | -------------------------------------------------------------------------------- /memcached-sr/t/authfile: -------------------------------------------------------------------------------- 1 | foo:bar 2 | baaaz:quux 3 | -------------------------------------------------------------------------------- /memcached-sr/t/binary-get.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 8; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | 12 | my $count = 1; 13 | 14 | foreach my $blob ("mooo\0", "mumble\0\0\0\0\r\rblarg", "\0", "\r") { 15 | my $key = "foo$count"; 16 | my $len = length($blob); 17 | print "len is $len\n"; 18 | print $sock "set $key 0 0 $len\r\n$blob\r\n"; 19 | is(scalar <$sock>, "STORED\r\n", "stored $key"); 20 | mem_get_is($sock, $key, $blob); 21 | $count++; 22 | } 23 | 24 | -------------------------------------------------------------------------------- /memcached-sr/t/bogus-commands.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 1; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | 12 | print $sock "boguscommand slkdsldkfjsd\r\n"; 13 | is(scalar <$sock>, "ERROR\r\n", "got error back"); 14 | -------------------------------------------------------------------------------- /memcached-sr/t/cacert.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIDqzCCApOgAwIBAgIJAOFc3ZmVKolRMA0GCSqGSIb3DQEBBQUAMIGLMSgwJgYD 3 | VQQDDB9UZXN0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQswCQYDVQQIDAJD 4 | QTELMAkGA1UEBhMCVVMxHDAaBgkqhkiG9w0BCQEWDXJvb3RAdGVzdC5jb20xDTAL 5 | BgNVBAoMBFRlc3QxGDAWBgNVBAsMD1Rlc3QgRGVwYXJ0bWVudDAeFw0xOTAxMDcx 6 | ODIzMjlaFw0yNDAxMDYxODIzMjlaMIGLMSgwJgYDVQQDDB9UZXN0IFJvb3QgQ2Vy 7 | dGlmaWNhdGUgQXV0aG9yaXR5MQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMxHDAa 8 | BgkqhkiG9w0BCQEWDXJvb3RAdGVzdC5jb20xDTALBgNVBAoMBFRlc3QxGDAWBgNV 9 | BAsMD1Rlc3QgRGVwYXJ0bWVudDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC 10 | ggEBAJQcDfenVed0uJCykaWowL2qGUs9e5gyjGo9URoNhI5LDYSSq3ebxZGfbi1T 11 | BcC7oL5OI/B0lCShPR9sJjKFkQ60vs43ltmkTLNSGoKLnxXMlBjdpCxweDDAMiF3 12 | p/vCG2hUa7auOkMWMYIkM81rcQsRB0qj0ilt3zcTsS860oKGzNrtPeAcz3KxbYWI 13 | nJEhQVy3S4U59b7mm3cGz3/3m2NUjn+b8sA7J8F9K5mnFkCUCRva6zte6qmL2ruH 14 | sGRav9ICLGxDqiJoic6Y2ReffgU77RDJO+sTuJme+VeTDE77vBIHvCVCSG+e0RSs 15 | L+6nQYDtjHH5bLgoSXq9D3hgxEsCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkq 16 | hkiG9w0BAQUFAAOCAQEARWcYJvkleq+qfOPPI1eQAuBf5OZwz8mthsBvMfsQMCLk 17 | +wSxdlJvJyvPoFgZBv8YbTde2b40lQe94gTsGDUXGEkOsERrjt/jqHxO9X8n7a+z 18 | M/okeSSYnam0Zcl1M9sa5L7BVXbGh/sE9j/bXrAhz64np5P773dZTLTPYjBf2Grp 19 | NheCsGDtJbegJqn7pp5MfAKcyzLxnZAE0cilSVKZB7R3urISJVdwiRtkprJL7IwQ 20 | oIu+XhUgdZbx7TQQnjTkq3COSIIof5+5oqFnhzTqfSgi/06dWWvCwl17Mz+vCMZ9 21 | 1MA8L4cR+iNdJYlCQPbk30laJx1akfqnpv7qTXq7nQ== 22 | -----END CERTIFICATE----- 23 | -------------------------------------------------------------------------------- /memcached-sr/t/cakey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN ENCRYPTED PRIVATE KEY----- 2 | MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQIigxGWoxgfJACAggA 3 | MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECHgfMUpgAX2tBIIEyFcJT6kFw1TH 4 | kmwmbtB+MPW3+zUxoKZuP+L7UCaMHQPHcQ4/AThVNPPhXa++/lgL0P1q33SBhqsm 5 | HK5nRfzEe75bQIFoZ1FFg3YGaAB4KUPm5vJ4XhmyzCEiUvp75mgiw38fkL5ZCPqW 6 | eitNKgyAYEl9zIrF1cRyN/s6O6mPR8NOPbVL2ZtCGGvy/LN+mhlolvuMFySEEI+s 7 | nzu5682LU7QQOzLFB/q3Vqrt2tafzoIHYtj8YYVsPMO6bWkoKx1BWyTCuesFOLTN 8 | agnXx3AKtmD8Q0C3vvdmpqNnWw1iP1Vc4r/BZwmD2MFXUh8cExBGRaPIfUr41BoR 9 | p1bHqtcAsbipuU7qQ6wjnLyuqAvFQxy1LCBGNyBrzMMD25+lXh9BoeS9H5L+WW0N 10 | pcAPA5FoD1RQc27ZXVf0kRGEy8Vj/UsE3Pf74Z8u16bC+6ojAUvvvc49ERm0t85O 11 | T5rP9ql3sITtg4EvNdNhHtYdJGVkZQ7H8T9G1OXEf4dE/vqYNnqhtFm+5CyWb8Vk 12 | Rly2XFbBs4I4UnVIi0Nt0ybIqqwAvvKAU5kSOIEy6Q9mvUYyvBZrhY5Va2KEwaTU 13 | ig2yjWxWFoOArE1UVu2kJaslaOKqAr9OPqW510+6G9s+lREm7EYqUd6Ut1cwcXUv 14 | /s1fdx/As6U6qApH9+TC0XqNm5yXNCuADVtK2PmOoanczpEXZTZGijylGFDROQQj 15 | bofjoB0hiN80Xc+II0zClGwXwZz43Xy4uVIMbvMBi3yp03ct1RMwORPCGkiH/1uV 16 | iazsfV4DAD8KdGmgUL57WfnMPZJCEfqpM4YrM7rKu3Md8v8hKyFGUAdeNsCFTwwY 17 | g2E6NXWbtqGrUFC/r/70/axfijWRoyPaLcBoourc5HcZ+K/TmmY+uOxKBcJsfS/t 18 | HiRZ5l48sva+lZVWN6KNG5N93pa3TqgCCfp56VPOo3o3kj4XAJ3aMK6RsK3QrGi7 19 | TTXlv/hKFYW3GUJ0IGNfinnARbdMoD6ww8nQLe3Id3HKzqh7xfQb4xJZpQhpSXVS 20 | KJmf5H80GHQnJq54Xwi7daYmxpTS+yNHuxKq+ryBqO7WeotNkOCbG6Flc/GBO6a3 21 | 7rbSOTmqpyJPTRPQEf1ogHNgCG9txPIbZRAi9PPJVn/gV/dKttUpj5OGI9fjDaSK 22 | ILEwLuokdRwTAGeFRIkucKnvA0pzXQkZRMG4D4kYzxskutUQVvKFAsqvEkb2c6qL 23 | j8MjKYfYZqxG44o68aOk8H42vR6lkemclj6byvLfnqbZPUka3MUnrG8oPI+vNLlg 24 | N57QpU2Kw5joBf1oCSROTXEv3BT/JYE3qQ2T6q/NGgG0s8aXbROh/7HaZJrENmoD 25 | pDJZp+bSGn6On6vmDu98F3fyubKgg611tA5pyDdWE4MSvJBGKHc2/HmqgxbLtK1c 26 | gn2BBefAi+Qqzc+XSeJxh2nlAx7ohvgEcodO3Vqb9eSoPviMHyO9bap8QIFJqTNW 27 | QK6rMqtou0QTEcXp5cIlVRW59zZHKEPpNpJ08fNtxB5n/Ngo+vo86LLVUysfbwkY 28 | p7GK4kraBGhU3rEXzuFBXn1Cr7015VrAC8mLafKqar7OLhLduHDRPxGidXJc6oxE 29 | 2PpJudZFhS6P+0M5AkMq2Q== 30 | -----END ENCRYPTED PRIVATE KEY----- 31 | -------------------------------------------------------------------------------- /memcached-sr/t/client_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXAIBAAKBgQCmpCQZFJ6WCj64FHvpBMqg72Ea5mOEUTQQWJ7yb50nZOWpMgLi 3 | +/DFR9Cyj/QZcSre+N6uywtBz8x2Y5tKmxJQX7m0/OP9BYV/pxyt7NFAcPpMUYij 4 | 1OVJsnJ8Lk3FAK5AlhWENF+ZdXtqANPsoH2C03GjeczUTDtQSdCbJ+QLywIDAQAB 5 | AoGAXFVMrxzutiIdGHA5LCb8g2m/+2C2uYUo/PmtsJVJlZ9hZXuRf+WrRhSBvb7n 6 | uQUshPmOoXld1mxmVR7h19fOsBbgKYqwDTlLZEnvdMVzaGiyeHiwDAvJgkkrK7pV 7 | kod5JIjFd+UMho6+Qn3K7tzfttLze5xuBPNrMH3q2b8LgBECQQDbJVyF+gLk4gmd 8 | BBInYl0BHPjYmGW9xfHfn0fhkKhQCZ9eNzH5Wbk1D8yqdlfmJ5nI8FkLQunzwzgv 9 | P51m+USJAkEAwqpaJoVOaaRfmsgEXOsZop32DBCBHwOqOyqH9qMez8qfBPDHrUbA 10 | TMtJN/TqLhi4VEPeaHbioUdUybA+1MggswJALWEgNrId1U2lVflY1QT+Y1OfiCKO 11 | tux9eKQgG2p8IA7ODJF7bLoSqxU5eXcGHqfGpaB3n+hcT9j2Enqm2oL1mQJAIp53 12 | D9ivPDxeQEGH/RpWYcQjyLt6qxBUytbifSs/RIbtRsynRhqKAl44tDnbF72PsnSr 13 | bfqOjU4JNyEf22mH3wJBAK1yx2ilG//KYHtcfFYtll0Rkkife+2It6bTMVdkeVCH 14 | o5iDnW/+VsJCawhS9jHLZAjors+A9iyjygl1O6zLZTE= 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /memcached-sr/t/daemonize.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 7; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | use File::Temp qw(tempfile); 10 | 11 | my (undef, $tmpfn) = tempfile(); 12 | 13 | my $server = new_memcached("-d -P $tmpfn"); 14 | my $sock = $server->sock; 15 | sleep 0.5; 16 | 17 | ok(-e $tmpfn, "pid file exists"); 18 | ok(-s $tmpfn, "pid file has length"); 19 | 20 | open (my $fh, $tmpfn) or die; 21 | my $readpid = do { local $/; <$fh>; }; 22 | chomp $readpid; 23 | close ($fh); 24 | 25 | ok(kill(0, $readpid), "process is still running"); 26 | 27 | my $stats = mem_stats($sock); 28 | is($stats->{pid}, $readpid, "memcached reports same pid as file"); 29 | 30 | ok($server->new_sock, "opened new socket"); 31 | ok(kill(9, $readpid), "sent KILL signal"); 32 | sleep 0.5; 33 | ok(! $server->new_sock, "failed to open new socket"); 34 | -------------------------------------------------------------------------------- /memcached-sr/t/dash-M.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached('-M -m 2'); 10 | my $sock = $server->sock; 11 | 12 | my $value = "B" x 8192; 13 | my $vallen = length($value); 14 | 15 | my $resp = "STORED\r\n"; 16 | my $key = 0; 17 | 18 | while($resp eq "STORED\r\n") { 19 | print $sock "set dash$key 0 0 $vallen\r\n$value\r\n"; 20 | $key++; 21 | $resp = scalar <$sock>; 22 | } 23 | 24 | my $max_stored = $key - 1; 25 | 26 | plan tests => $max_stored + 1; 27 | 28 | print $sock "set dash$key 0 0 $vallen\r\n$value\r\n"; 29 | is(scalar <$sock>, "SERVER_ERROR out of memory storing object\r\n", 30 | "failed to add another one."); 31 | 32 | for($key = 0; $key < $max_stored; $key++) { 33 | mem_get_is $sock, "dash$key", $value, "Failed at dash$key"; 34 | } 35 | -------------------------------------------------------------------------------- /memcached-sr/t/dyn-maxbytes.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # Test the 'stats items' evictions counters. 3 | 4 | use strict; 5 | use Test::More tests => 309; 6 | use FindBin qw($Bin); 7 | use lib "$Bin/lib"; 8 | use MemcachedTest; 9 | 10 | my $server = new_memcached("-m 3 -o modern,slab_automove_window=3"); 11 | my $sock = $server->sock; 12 | my $value = "B"x66560; 13 | my $key = 0; 14 | 15 | # These aren't set to expire. 16 | for ($key = 0; $key < 40; $key++) { 17 | print $sock "set key$key 0 0 66560\r\n$value\r\n"; 18 | is(scalar <$sock>, "STORED\r\n", "stored key$key"); 19 | } 20 | 21 | my $stats = mem_stats($sock); 22 | my $evicted = $stats->{evictions}; 23 | isnt($evicted, "0", "check evicted"); 24 | 25 | # We're past the memory limit. Try adjusting maxbytes upward. 26 | $stats = mem_stats($sock, "settings"); 27 | my $pre_maxbytes = $stats->{"maxbytes"}; 28 | print $sock "cache_memlimit 8\r\n"; 29 | is(scalar <$sock>, "OK\r\n", "bumped maxbytes from 3m to 8m"); 30 | 31 | # Confirm maxbytes updated. 32 | $stats = mem_stats($sock, "settings"); 33 | isnt($stats->{"maxbytes"}, $pre_maxbytes, "stats settings maxbytes updated"); 34 | 35 | # Check for total_malloced increasing as new memory is added 36 | $stats = mem_stats($sock, "slabs"); 37 | my $t_malloc = $stats->{"total_malloced"}; 38 | 39 | print $sock "set toast 0 0 66560\r\n$value\r\n"; 40 | is(scalar <$sock>, "STORED\r\n", "stored toast"); 41 | $stats = mem_stats($sock, "slabs"); 42 | cmp_ok($stats->{"total_malloced"}, '>', $t_malloc, "stats slabs total_malloced increased"); 43 | 44 | $stats = mem_stats($sock); 45 | my $new_evicted = $stats->{evictions}; 46 | cmp_ok($new_evicted, '==', $evicted, "no new evictions"); 47 | 48 | # Bump up to 16, fill a bit more, then delete everything. 49 | print $sock "cache_memlimit 16\r\n"; 50 | is(scalar <$sock>, "OK\r\n", "bumped maxbytes from 8m to 16m"); 51 | for (;$key < 150; $key++) { 52 | print $sock "set key$key 0 0 66560\r\n$value\r\n"; 53 | is(scalar <$sock>, "STORED\r\n", "stored key$key"); 54 | } 55 | 56 | # Grab total_malloced after filling everything up. 57 | $stats = mem_stats($sock, "slabs"); 58 | $t_malloc = $stats->{"total_malloced"}; 59 | print $sock "cache_memlimit 8\r\n"; 60 | is(scalar <$sock>, "OK\r\n", "bumped maxbytes from 16m to 8m"); 61 | 62 | # Remove all of the keys, allowing the slab rebalancer to push pages toward 63 | # the global page pool. 64 | for ($key = 0; $key < 150; $key++) { 65 | print $sock "delete key$key\r\n"; 66 | like(scalar <$sock>, qr/(DELETED|NOT_FOUND)\r\n/, "deleted key$key"); 67 | } 68 | 69 | # If memory limit is lower, it should free those pages back to the OS. 70 | my $reduced = 0; 71 | for (my $tries = 0; $tries < 6; $tries++) { 72 | sleep 1; 73 | $stats = mem_stats($sock, "slabs"); 74 | $reduced = $stats->{"total_malloced"} if ($t_malloc > $stats->{"total_malloced"}); 75 | last if $reduced; 76 | } 77 | 78 | isnt($reduced, 0, "total_malloced reduced to $reduced"); 79 | -------------------------------------------------------------------------------- /memcached-sr/t/evictions.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # Test the 'stats items' evictions counters. 3 | 4 | use strict; 5 | use Test::More tests => 92; 6 | use FindBin qw($Bin); 7 | use lib "$Bin/lib"; 8 | use MemcachedTest; 9 | 10 | my $server = new_memcached("-m 3"); 11 | my $sock = $server->sock; 12 | my $value = "B"x66560; 13 | my $key = 0; 14 | 15 | # These aren't set to expire. 16 | for ($key = 0; $key < 40; $key++) { 17 | print $sock "set key$key 0 0 66560\r\n$value\r\n"; 18 | is(scalar <$sock>, "STORED\r\n", "stored key$key"); 19 | } 20 | 21 | # These ones would expire in 600 seconds. 22 | for ($key = 0; $key < 50; $key++) { 23 | print $sock "set key$key 0 600 66560\r\n$value\r\n"; 24 | is(scalar <$sock>, "STORED\r\n", "stored key$key"); 25 | } 26 | 27 | my $stats = mem_stats($sock, "items"); 28 | my $evicted = $stats->{"items:31:evicted"}; 29 | isnt($evicted, "0", "check evicted"); 30 | my $evicted_nonzero = $stats->{"items:31:evicted_nonzero"}; 31 | isnt($evicted_nonzero, "0", "check evicted_nonzero"); 32 | -------------------------------------------------------------------------------- /memcached-sr/t/expirations.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 15; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | my $expire; 12 | 13 | sub wait_for_early_second { 14 | my $have_hires = eval "use Time::HiRes (); 1"; 15 | if ($have_hires) { 16 | my $tsh = Time::HiRes::time(); 17 | my $ts = int($tsh); 18 | return if ($tsh - $ts) < 0.5; 19 | } 20 | 21 | my $ts = int(time()); 22 | while (1) { 23 | my $t = int(time()); 24 | return if $t != $ts; 25 | select undef, undef, undef, 0.10; # 1/10th of a second sleeps until time changes. 26 | } 27 | } 28 | 29 | wait_for_early_second(); 30 | 31 | print $sock "set foo 0 3 6\r\nfooval\r\n"; 32 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 33 | 34 | mem_get_is($sock, "foo", "fooval"); 35 | sleep(4); 36 | mem_get_is($sock, "foo", undef); 37 | 38 | $expire = time() - 1; 39 | print $sock "set foo 0 $expire 6\r\nfooval\r\n"; 40 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 41 | mem_get_is($sock, "foo", undef, "already expired"); 42 | 43 | $expire = time() + 1; 44 | print $sock "set foo 0 $expire 6\r\nfoov+1\r\n"; 45 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 46 | mem_get_is($sock, "foo", "foov+1"); 47 | sleep(2.2); 48 | mem_get_is($sock, "foo", undef, "now expired"); 49 | 50 | $expire = time() - 20; 51 | print $sock "set boo 0 $expire 6\r\nbooval\r\n"; 52 | is(scalar <$sock>, "STORED\r\n", "stored boo"); 53 | mem_get_is($sock, "boo", undef, "now expired"); 54 | 55 | print $sock "add add 0 2 6\r\naddval\r\n"; 56 | is(scalar <$sock>, "STORED\r\n", "stored add"); 57 | mem_get_is($sock, "add", "addval"); 58 | # second add fails 59 | print $sock "add add 0 2 7\r\naddval2\r\n"; 60 | is(scalar <$sock>, "NOT_STORED\r\n", "add failure"); 61 | sleep(2.3); 62 | print $sock "add add 0 2 7\r\naddval3\r\n"; 63 | is(scalar <$sock>, "STORED\r\n", "stored add again"); 64 | mem_get_is($sock, "add", "addval3"); 65 | -------------------------------------------------------------------------------- /memcached-sr/t/extstore-buckets.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | use FindBin qw($Bin); 7 | use lib "$Bin/lib"; 8 | use MemcachedTest; 9 | use Data::Dumper qw/Dumper/; 10 | 11 | my $ext_path; 12 | 13 | if (!supports_extstore()) { 14 | plan skip_all => 'extstore not enabled'; 15 | exit 0; 16 | } 17 | 18 | $ext_path = "/tmp/extstore.$$"; 19 | 20 | my $server = new_memcached("-m 256 -U 0 -o ext_page_size=8,ext_wbuf_size=2,ext_threads=1,ext_io_depth=2,ext_item_size=512,ext_item_age=2,ext_recache_rate=10000,ext_max_frag=0,ext_path=$ext_path:64m,ext_low_ttl=60,slab_automove=1"); 21 | my $sock = $server->sock; 22 | 23 | my $value; 24 | { 25 | my @chars = ("C".."Z"); 26 | for (1 .. 20000) { 27 | $value .= $chars[rand @chars]; 28 | } 29 | } 30 | 31 | # fill some larger objects 32 | { 33 | # interleave sets with 0 ttl vs long ttl's. 34 | my $keycount = 1200; 35 | for (1 .. $keycount) { 36 | print $sock "set nfoo$_ 0 0 20000 noreply\r\n$value\r\n"; 37 | print $sock "set lfoo$_ 0 5 20000 noreply\r\n$value\r\n"; 38 | } 39 | # wait for a flush 40 | sleep 10; 41 | print $sock "lru_crawler crawl all\r\n"; 42 | <$sock>; 43 | sleep 2; 44 | # fetch 45 | mem_get_is($sock, "nfoo1", $value); 46 | # check extstore counters 47 | my $stats = mem_stats($sock); 48 | cmp_ok($stats->{extstore_page_allocs}, '>', 0, 'at least one page allocated'); 49 | cmp_ok($stats->{extstore_objects_written}, '>', $keycount / 2, 'some objects written'); 50 | cmp_ok($stats->{extstore_bytes_written}, '>', length($value) * 2, 'some bytes written'); 51 | cmp_ok($stats->{get_extstore}, '>', 0, 'one object was fetched'); 52 | cmp_ok($stats->{extstore_objects_read}, '>', 0, 'one object read'); 53 | cmp_ok($stats->{extstore_bytes_read}, '>', length($value), 'some bytes read'); 54 | cmp_ok($stats->{extstore_page_reclaims}, '>', 1, 'at least two pages reclaimed'); 55 | } 56 | 57 | done_testing(); 58 | 59 | END { 60 | unlink $ext_path if $ext_path; 61 | } 62 | -------------------------------------------------------------------------------- /memcached-sr/t/extstore-jbod.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | use FindBin qw($Bin); 7 | use lib "$Bin/lib"; 8 | use MemcachedTest; 9 | use Data::Dumper qw/Dumper/; 10 | 11 | my $ext_path; 12 | my $ext_path2; 13 | 14 | if (!supports_extstore()) { 15 | plan skip_all => 'extstore not enabled'; 16 | exit 0; 17 | } 18 | 19 | $ext_path = "/tmp/extstore1.$$"; 20 | $ext_path2 = "/tmp/extstore2.$$"; 21 | 22 | my $server = new_memcached("-m 256 -U 0 -o ext_page_size=8,ext_wbuf_size=2,ext_threads=1,ext_io_depth=2,ext_item_size=512,ext_item_age=2,ext_recache_rate=10000,ext_max_frag=0.9,ext_path=$ext_path:64m,ext_path=$ext_path2:96m,slab_automove=1"); 23 | my $sock = $server->sock; 24 | 25 | my $value; 26 | { 27 | my @chars = ("C".."Z"); 28 | for (1 .. 20000) { 29 | $value .= $chars[rand @chars]; 30 | } 31 | } 32 | 33 | # fill some larger objects 34 | { 35 | # interleave sets with 0 ttl vs long ttl's. 36 | my $keycount = 3700; 37 | for (1 .. $keycount) { 38 | print $sock "set nfoo$_ 0 0 20000 noreply\r\n$value\r\n"; 39 | print $sock "set lfoo$_ 0 0 20000 noreply\r\n$value\r\n"; 40 | } 41 | # wait for a flush 42 | wait_ext_flush($sock); 43 | # delete half 44 | mem_get_is($sock, "nfoo1", $value); 45 | for (1 .. $keycount) { 46 | print $sock "delete lfoo$_ noreply\r\n"; 47 | } 48 | print $sock "lru_crawler crawl all\r\n"; 49 | <$sock>; 50 | sleep 10; 51 | # fetch 52 | # check extstore counters 53 | my $stats = mem_stats($sock); 54 | is($stats->{evictions}, 0, 'no RAM evictions'); 55 | cmp_ok($stats->{extstore_page_allocs}, '>', 0, 'at least one page allocated'); 56 | cmp_ok($stats->{extstore_objects_written}, '>', $keycount / 2, 'some objects written'); 57 | cmp_ok($stats->{extstore_bytes_written}, '>', length($value) * 2, 'some bytes written'); 58 | cmp_ok($stats->{get_extstore}, '>', 0, 'one object was fetched'); 59 | cmp_ok($stats->{extstore_objects_read}, '>', 0, 'one object read'); 60 | cmp_ok($stats->{extstore_bytes_read}, '>', length($value), 'some bytes read'); 61 | cmp_ok($stats->{extstore_page_reclaims}, '>', 1, 'at least two pages reclaimed'); 62 | } 63 | 64 | done_testing(); 65 | 66 | END { 67 | unlink $ext_path if $ext_path; 68 | unlink $ext_path2 if $ext_path2; 69 | } 70 | -------------------------------------------------------------------------------- /memcached-sr/t/flags.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 8; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | 12 | # set foo (and should get it) 13 | for my $flags (0, 123, 2**16-1, 2**31) { 14 | print $sock "set foo $flags 0 6\r\nfooval\r\n"; 15 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 16 | mem_get_is({ sock => $sock, 17 | flags => $flags }, "foo", "fooval", "got flags $flags back"); 18 | } 19 | -------------------------------------------------------------------------------- /memcached-sr/t/flush-all.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 26; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | my $expire; 12 | 13 | print $sock "set foo 0 0 6\r\nfooval\r\n"; 14 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 15 | 16 | mem_get_is($sock, "foo", "fooval"); 17 | print $sock "flush_all\r\n"; 18 | is(scalar <$sock>, "OK\r\n", "did flush_all"); 19 | mem_get_is($sock, "foo", undef); 20 | 21 | # Test flush_all with zero delay. 22 | print $sock "set foo 0 0 6\r\nfooval\r\n"; 23 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 24 | 25 | mem_get_is($sock, "foo", "fooval"); 26 | print $sock "flush_all 0\r\n"; 27 | is(scalar <$sock>, "OK\r\n", "did flush_all"); 28 | mem_get_is($sock, "foo", undef); 29 | 30 | # check that flush_all doesn't blow away items that immediately get set 31 | print $sock "set foo 0 0 3\r\nnew\r\n"; 32 | is(scalar <$sock>, "STORED\r\n", "stored foo = 'new'"); 33 | mem_get_is($sock, "foo", 'new'); 34 | 35 | # and the other form, specifying a flush_all time... 36 | my $expire = time() + 2; 37 | print $sock "flush_all $expire\r\n"; 38 | is(scalar <$sock>, "OK\r\n", "did flush_all in future"); 39 | 40 | print $sock "set foo 0 0 4\r\n1234\r\n"; 41 | is(scalar <$sock>, "STORED\r\n", "stored foo = '1234'"); 42 | mem_get_is($sock, "foo", '1234'); 43 | sleep(5); 44 | mem_get_is($sock, "foo", undef); 45 | 46 | print $sock "set foo 0 0 5\r\n12345\r\n"; 47 | is(scalar <$sock>, "STORED\r\n", "stored foo = '12345'"); 48 | mem_get_is($sock, "foo", '12345'); 49 | print $sock "flush_all 86400\r\n"; 50 | is(scalar <$sock>, "OK\r\n", "did flush_all for far future"); 51 | # Check foo still exists. 52 | mem_get_is($sock, "foo", '12345'); 53 | print $sock "set foo2 0 0 5\r\n54321\r\n"; 54 | is(scalar <$sock>, "STORED\r\n", "stored foo2 = '54321'"); 55 | mem_get_is($sock, "foo", '12345'); 56 | mem_get_is($sock, "foo2", '54321'); 57 | 58 | # Test -F option which disables flush_all 59 | $server = new_memcached('-F'); 60 | $sock = $server->sock; 61 | 62 | print $sock "set foo 0 0 7\r\nfooval2\r\n"; 63 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 64 | 65 | mem_get_is($sock, "foo", "fooval2"); 66 | print $sock "flush_all\r\n"; 67 | is(scalar <$sock>, "CLIENT_ERROR flush_all not allowed\r\n", "flush_all was not allowed"); 68 | mem_get_is($sock, "foo", "fooval2"); 69 | 70 | # Test that disabling CAS makes flush_all less accurate. 71 | # Due to lock ordering issues we can no longer evict items newer than 72 | # oldest_live, so we rely on the CAS counter for an exact cliff. So disabling 73 | # CAS now means all items set in the same second will fail to set. 74 | $server = new_memcached('-C'); 75 | $sock = $server->sock; 76 | 77 | my $failed_nocas = 0; 78 | # Running this 100,000 times failed the test a handful of times. 50 tries 79 | # should be enough. 80 | for (1..50) { 81 | print $sock "flush_all 0\r\n"; 82 | my $foo = scalar <$sock>; 83 | print $sock "set foo 0 0 3\r\nnew\r\n"; 84 | $foo = scalar <$sock>; 85 | print $sock "get foo\r\n"; 86 | my $line = scalar <$sock>; 87 | if ($line =~ /^VALUE/) { 88 | $line = scalar <$sock>; 89 | $line = scalar <$sock>; 90 | print STDERR "Succeeded!!!\n"; 91 | next; 92 | } elsif ($line =~ /^END/) { 93 | $failed_nocas++; 94 | last; 95 | } 96 | } 97 | is($failed_nocas, 1, "failed to set value after flush with no CAS at least once"); 98 | -------------------------------------------------------------------------------- /memcached-sr/t/getandtouch.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More tests => 15; 6 | use FindBin qw($Bin); 7 | use lib "$Bin/lib"; 8 | use MemcachedTest; 9 | 10 | 11 | my $server = new_memcached(); 12 | my $sock = $server->sock; 13 | 14 | # cache miss 15 | print $sock "gat 10 foo1\r\n"; 16 | is(scalar <$sock>, "END\r\n", "cache miss"); 17 | 18 | # set foo1 and foo2 (and should get it) 19 | print $sock "set foo1 0 2 7\r\nfooval1\r\n"; 20 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 21 | 22 | print $sock "set foo2 0 2 7\r\nfooval2\r\n"; 23 | is(scalar <$sock>, "STORED\r\n", "stored foo2"); 24 | 25 | # get and touch it with cas 26 | print $sock "gats 10 foo1 foo2\r\n"; 27 | ok(scalar <$sock> =~ /VALUE foo1 0 7 (\d+)\r\n/, "get and touch foo1 with cas regexp success"); 28 | is(scalar <$sock>, "fooval1\r\n","value"); 29 | ok(scalar <$sock> =~ /VALUE foo2 0 7 (\d+)\r\n/, "get and touch foo2 with cas regexp success"); 30 | is(scalar <$sock>, "fooval2\r\n","value"); 31 | is(scalar <$sock>, "END\r\n", "end"); 32 | 33 | # get and touch it without cas 34 | print $sock "gat 10 foo1 foo2\r\n"; 35 | ok(scalar <$sock> =~ /VALUE foo1 0 7\r\n/, "get and touch foo1 without cas regexp success"); 36 | is(scalar <$sock>, "fooval1\r\n","value"); 37 | ok(scalar <$sock> =~ /VALUE foo2 0 7\r\n/, "get and touch foo2 without cas regexp success"); 38 | is(scalar <$sock>, "fooval2\r\n","value"); 39 | is(scalar <$sock>, "END\r\n", "end"); 40 | 41 | sleep 2; 42 | mem_get_is($sock, "foo1", "fooval1"); 43 | mem_get_is($sock, "foo2", "fooval2"); 44 | -------------------------------------------------------------------------------- /memcached-sr/t/getset.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 539; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | 10 | my $server = new_memcached(); 11 | my $sock = $server->sock; 12 | 13 | 14 | # set foo (and should get it) 15 | print $sock "set foo 0 0 6\r\nfooval\r\n"; 16 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 17 | mem_get_is($sock, "foo", "fooval"); 18 | 19 | # add bar (and should get it) 20 | print $sock "add bar 0 0 6\r\nbarval\r\n"; 21 | is(scalar <$sock>, "STORED\r\n", "stored barval"); 22 | mem_get_is($sock, "bar", "barval"); 23 | 24 | # add foo (but shouldn't get new value) 25 | print $sock "add foo 0 0 5\r\nfoov2\r\n"; 26 | is(scalar <$sock>, "NOT_STORED\r\n", "not stored"); 27 | mem_get_is($sock, "foo", "fooval"); 28 | 29 | # replace bar (should work) 30 | print $sock "replace bar 0 0 6\r\nbarva2\r\n"; 31 | is(scalar <$sock>, "STORED\r\n", "replaced barval 2"); 32 | 33 | # replace notexist (shouldn't work) 34 | print $sock "replace notexist 0 0 6\r\nbarva2\r\n"; 35 | is(scalar <$sock>, "NOT_STORED\r\n", "didn't replace notexist"); 36 | 37 | # delete foo. 38 | print $sock "delete foo\r\n"; 39 | is(scalar <$sock>, "DELETED\r\n", "deleted foo"); 40 | 41 | # delete foo again. not found this time. 42 | print $sock "delete foo\r\n"; 43 | is(scalar <$sock>, "NOT_FOUND\r\n", "deleted foo, but not found"); 44 | 45 | # add moo 46 | # 47 | print $sock "add moo 0 0 6\r\nmooval\r\n"; 48 | is(scalar <$sock>, "STORED\r\n", "stored barval"); 49 | mem_get_is($sock, "moo", "mooval"); 50 | 51 | # check-and-set (cas) failure case, try to set value with incorrect cas unique val 52 | print $sock "cas moo 0 0 6 0\r\nMOOVAL\r\n"; 53 | is(scalar <$sock>, "EXISTS\r\n", "check and set with invalid id"); 54 | 55 | # test "gets", grab unique ID 56 | print $sock "gets moo\r\n"; 57 | # VALUE moo 0 6 3084947704 58 | # 59 | my @retvals = split(/ /, scalar <$sock>); 60 | my $data = scalar <$sock>; # grab data 61 | my $dot = scalar <$sock>; # grab dot on line by itself 62 | is($retvals[0], "VALUE", "get value using 'gets'"); 63 | my $unique_id = $retvals[4]; 64 | # clean off \r\n 65 | $unique_id =~ s/\r\n$//; 66 | ok($unique_id =~ /^\d+$/, "unique ID '$unique_id' is an integer"); 67 | # now test that we can store moo with the correct unique id 68 | print $sock "cas moo 0 0 6 $unique_id\r\nMOOVAL\r\n"; 69 | is(scalar <$sock>, "STORED\r\n"); 70 | mem_get_is($sock, "moo", "MOOVAL"); 71 | 72 | # pipeline is okay 73 | print $sock "set foo 0 0 6\r\nfooval\r\ndelete foo\r\nset foo 0 0 6\r\nfooval\r\ndelete foo\r\n"; 74 | is(scalar <$sock>, "STORED\r\n", "pipeline set"); 75 | is(scalar <$sock>, "DELETED\r\n", "pipeline delete"); 76 | is(scalar <$sock>, "STORED\r\n", "pipeline set"); 77 | is(scalar <$sock>, "DELETED\r\n", "pipeline delete"); 78 | 79 | 80 | # Test sets up to a large size around 1MB. 81 | # Everything up to 1MB - 1k should succeed, everything 1MB +1k should fail. 82 | 83 | my $len = 1024; 84 | while ($len < 1024*1028) { 85 | my $val = "B"x$len; 86 | if ($len > (1024*1024)) { 87 | # Ensure causing a memory overflow doesn't leave stale data. 88 | print $sock "set foo_$len 0 0 3\r\nMOO\r\n"; 89 | is(scalar <$sock>, "STORED\r\n"); 90 | print $sock "set foo_$len 0 0 $len\r\n$val\r\n"; 91 | is(scalar <$sock>, "SERVER_ERROR object too large for cache\r\n", "failed to store size $len"); 92 | mem_get_is($sock, "foo_$len"); 93 | } else { 94 | print $sock "set foo_$len 0 0 $len\r\n$val\r\n"; 95 | is(scalar <$sock>, "STORED\r\n", "stored size $len"); 96 | } 97 | $len += 2048; 98 | } 99 | 100 | -------------------------------------------------------------------------------- /memcached-sr/t/idle-timeout.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Test::More tests => 11; 7 | 8 | use FindBin qw($Bin); 9 | use lib "$Bin/lib"; 10 | use MemcachedTest; 11 | 12 | # start up a server with 10 maximum connections 13 | my $server = new_memcached("-o idle_timeout=3 -l 127.0.0.1"); 14 | my $sock = $server->sock; 15 | 16 | # Make sure we can talk to start with 17 | my $stats = mem_stats($sock); 18 | is($stats->{idle_kicks}, "0", "check stats initial"); 19 | isnt($sock->connected(), undef, "check connected"); 20 | 21 | # Make sure we don't timeout when active 22 | for (my $i = 0; $i < 6; $i++) { 23 | $stats = mem_stats($sock); 24 | isnt($stats->{version}, undef, "check active $i"); 25 | } 26 | $stats = mem_stats($sock); 27 | is($stats->{idle_kicks}, "0", "check stats 2"); 28 | 29 | # Make sure we do timeout when not 30 | sleep(5); 31 | mem_stats($sock); # Network activity, so socket code will see dead socket 32 | sleep(1); 33 | # we run SSL tests over TCP; hence IO::Socket::SSL returns 34 | # '' upon disconnecting with the server. 35 | if (enabled_tls_testing()) { 36 | is($sock->connected(),'', "check disconnected"); 37 | } else { 38 | is($sock->connected(),undef, "check disconnected"); 39 | } 40 | 41 | $sock = $server->sock; 42 | $stats = mem_stats($sock); 43 | isnt($stats->{idle_kicks}, 0, "check stats timeout"); 44 | -------------------------------------------------------------------------------- /memcached-sr/t/incrdecr.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 23; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | 12 | # Bug 21 13 | print $sock "set bug21 0 0 19\r\n9223372036854775807\r\n"; 14 | is(scalar <$sock>, "STORED\r\n", "stored text"); 15 | print $sock "incr bug21 1\r\n"; 16 | is(scalar <$sock>, "9223372036854775808\r\n", "bug21 incr 1"); 17 | print $sock "incr bug21 1\r\n"; 18 | is(scalar <$sock>, "9223372036854775809\r\n", "bug21 incr 2"); 19 | print $sock "decr bug21 1\r\n"; 20 | is(scalar <$sock>, "9223372036854775808\r\n", "bug21 decr"); 21 | 22 | print $sock "set num 0 0 1\r\n1\r\n"; 23 | is(scalar <$sock>, "STORED\r\n", "stored num"); 24 | mem_get_is($sock, "num", 1, "stored 1"); 25 | 26 | print $sock "incr num 1\r\n"; 27 | is(scalar <$sock>, "2\r\n", "+ 1 = 2"); 28 | mem_get_is($sock, "num", 2); 29 | 30 | print $sock "incr num 8\r\n"; 31 | is(scalar <$sock>, "10\r\n", "+ 8 = 10"); 32 | mem_get_is($sock, "num", 10); 33 | 34 | print $sock "decr num 1\r\n"; 35 | is(scalar <$sock>, "9\r\n", "- 1 = 9"); 36 | 37 | print $sock "decr num 9\r\n"; 38 | is(scalar <$sock>, "0\r\n", "- 9 = 0"); 39 | 40 | print $sock "decr num 5\r\n"; 41 | is(scalar <$sock>, "0\r\n", "- 5 = 0"); 42 | 43 | printf $sock "set num 0 0 10\r\n4294967296\r\n"; 44 | is(scalar <$sock>, "STORED\r\n", "stored 2**32"); 45 | 46 | print $sock "incr num 1\r\n"; 47 | is(scalar <$sock>, "4294967297\r\n", "4294967296 + 1 = 4294967297"); 48 | 49 | printf $sock "set num 0 0 %d\r\n18446744073709551615\r\n", length("18446744073709551615"); 50 | is(scalar <$sock>, "STORED\r\n", "stored 2**64-1"); 51 | 52 | print $sock "incr num 1\r\n"; 53 | is(scalar <$sock>, "0\r\n", "(2**64 - 1) + 1 = 0"); 54 | 55 | print $sock "decr bogus 5\r\n"; 56 | is(scalar <$sock>, "NOT_FOUND\r\n", "can't decr bogus key"); 57 | 58 | print $sock "decr incr 5\r\n"; 59 | is(scalar <$sock>, "NOT_FOUND\r\n", "can't incr bogus key"); 60 | 61 | print $sock "set bigincr 0 0 1\r\n0\r\n"; 62 | is(scalar <$sock>, "STORED\r\n", "stored bigincr"); 63 | print $sock "incr bigincr 18446744073709551610\r\n"; 64 | is(scalar <$sock>, "18446744073709551610\r\n"); 65 | 66 | print $sock "set text 0 0 2\r\nhi\r\n"; 67 | is(scalar <$sock>, "STORED\r\n", "stored hi"); 68 | print $sock "incr text 1\r\n"; 69 | is(scalar <$sock>, 70 | "CLIENT_ERROR cannot increment or decrement non-numeric value\r\n", 71 | "hi - 1 = 0"); 72 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_104.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 6; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | 12 | # first get should miss 13 | print $sock "get foo\r\n"; 14 | is(scalar <$sock>, "END\r\n", "get foo"); 15 | 16 | # Now set and get (should hit) 17 | print $sock "set foo 0 0 6\r\nfooval\r\n"; 18 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 19 | mem_get_is($sock, "foo", "fooval"); 20 | 21 | my $stats = mem_stats($sock); 22 | is($stats->{cmd_get}, 2, "Should have 2 get requests"); 23 | is($stats->{get_hits}, 1, "Should have 1 hit"); 24 | is($stats->{get_misses}, 1, "Should have 1 miss"); 25 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_108.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 4; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | my $key = "del_key"; 12 | 13 | print $sock "add $key 0 0 1\r\nx\r\n"; 14 | is (scalar <$sock>, "STORED\r\n", "Added a key"); 15 | 16 | print $sock "delete $key 0\r\n"; 17 | is (scalar <$sock>, "DELETED\r\n", "Properly deleted with 0"); 18 | 19 | print $sock "add $key 0 0 1\r\nx\r\n"; 20 | is (scalar <$sock>, "STORED\r\n", "Added again a key"); 21 | 22 | print $sock "delete $key 0 noreply\r\n"; 23 | # will not reply, but a subsequent add will succeed 24 | 25 | print $sock "add $key 0 0 1\r\nx\r\n"; 26 | is (scalar <$sock>, "STORED\r\n", "Add succeeded after quiet deletion."); 27 | 28 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_14.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 21; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | my $value = "B"x66560; 12 | my $key = 0; 13 | 14 | for ($key = 0; $key < 10; $key++) { 15 | print $sock "set key$key 0 2 66560\r\n$value\r\n"; 16 | is (scalar <$sock>, "STORED\r\n", "stored key$key"); 17 | } 18 | 19 | #print $sock "stats slabs" 20 | my $first_stats = mem_stats($sock, "slabs"); 21 | my $first_malloc = $first_stats->{total_malloced}; 22 | 23 | sleep(4); 24 | 25 | for ($key = 10; $key < 20; $key++) { 26 | print $sock "set key$key 0 2 66560\r\n$value\r\n"; 27 | is (scalar <$sock>, "STORED\r\n", "stored key$key"); 28 | } 29 | 30 | my $second_stats = mem_stats($sock, "slabs"); 31 | my $second_malloc = $second_stats->{total_malloced}; 32 | 33 | 34 | is ($second_malloc, $first_malloc, "Memory grows..") 35 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_140.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | plan skip_all => 'Fix for Issue 140 was only an illusion'; 10 | 11 | plan tests => 7; 12 | 13 | my $server = new_memcached(); 14 | my $sock = $server->sock; 15 | 16 | print $sock "set a 0 0 1\r\na\r\n"; 17 | is (scalar <$sock>, "STORED\r\n", "stored key"); 18 | 19 | my $stats = mem_stats($sock, "items"); 20 | my $age = $stats->{"items:1:age"}; 21 | isnt ($age, "0", "Age should not be zero"); 22 | 23 | print $sock "flush_all\r\n"; 24 | is (scalar <$sock>, "OK\r\n", "items flushed"); 25 | 26 | my $stats = mem_stats($sock, "items"); 27 | my $age = $stats->{"items:1:age"}; 28 | is ($age, undef, "all should be gone"); 29 | 30 | print $sock "set a 0 1 1\r\na\r\n"; 31 | is (scalar <$sock>, "STORED\r\n", "stored key"); 32 | 33 | my $stats = mem_stats($sock, "items"); 34 | my $age = $stats->{"items:1:age"}; 35 | isnt ($age, "0", "Age should not be zero"); 36 | 37 | sleep(3); 38 | 39 | my $stats = mem_stats($sock, "items"); 40 | my $age = $stats->{"items:1:age"}; 41 | is ($age, undef, "all should be gone"); 42 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_152.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 2; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | my $key = "a"x251; 12 | 13 | print $sock "set a 1 0 1\r\na\r\n"; 14 | is (scalar <$sock>, "STORED\r\n", "Stored key"); 15 | 16 | print $sock "get a $key\r\n"; 17 | is (scalar <$sock>, "CLIENT_ERROR bad command line format\r\n", "illegal key"); 18 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_163.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 7; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | my $value1 = "A"x66560; 12 | my $value2 = "B"x66570; 13 | 14 | print $sock "set key 0 1 66560\r\n$value1\r\n"; 15 | is (scalar <$sock>, "STORED\r\n", "stored key"); 16 | 17 | my $stats = mem_stats($sock, "slabs"); 18 | my $requested = $stats->{"31:mem_requested"}; 19 | isnt ($requested, "0", "We should have requested some memory"); 20 | 21 | sleep(3); 22 | print $sock "set key 0 0 66570\r\n$value2\r\n"; 23 | is (scalar <$sock>, "STORED\r\n", "stored key"); 24 | 25 | my $stats = mem_stats($sock, "items"); 26 | my $reclaimed = $stats->{"items:31:reclaimed"}; 27 | is ($reclaimed, "1", "Objects should be reclaimed"); 28 | 29 | print $sock "delete key\r\n"; 30 | is (scalar <$sock>, "DELETED\r\n", "deleted key"); 31 | 32 | print $sock "set key 0 0 66560\r\n$value1\r\n"; 33 | is (scalar <$sock>, "STORED\r\n", "stored key"); 34 | 35 | my $stats = mem_stats($sock, "slabs"); 36 | my $requested2 = $stats->{"31:mem_requested"}; 37 | is ($requested2, $requested, "we've not allocated and freed the same amount"); 38 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_183.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 5; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached("-o no_modern"); 10 | my $sock = $server->sock; 11 | print $sock "set key 0 0 1\r\n1\r\n"; 12 | is (scalar <$sock>, "STORED\r\n", "stored key"); 13 | my $s1 = mem_stats($sock); 14 | my $r1 = $s1->{"reclaimed"}; 15 | is ($r1, "0", "Objects should not be reclaimed"); 16 | sleep(2); 17 | print $sock "flush_all\r\n"; 18 | is (scalar <$sock>, "OK\r\n", "Cache flushed"); 19 | print $sock "set key 0 0 1\r\n1\r\n"; 20 | is (scalar <$sock>, "STORED\r\n", "stored key"); 21 | my $s2 = mem_stats($sock); 22 | my $r2 = $s2->{"reclaimed"}; 23 | is ($r2, "1", "Objects should be reclaimed"); 24 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_192.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 2; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | 12 | ok($server->new_sock, "opened new socket"); 13 | 14 | print $sock "\x80\x12\x00\x01\x08\x00\x00\x00\xff\xff\xff\xe8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x01\x00\x00\x00\x00\x00\x00\x00\x00\x000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; 15 | 16 | sleep 0.5; 17 | ok($server->new_sock, "failed to open new socket"); 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_22.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 84; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached("-m 3"); 10 | my $sock = $server->sock; 11 | my $value = "B"x66560; 12 | my $key = 0; 13 | 14 | for ($key = 0; $key < 40; $key++) { 15 | print $sock "set key$key 0 0 66560\r\n$value\r\n"; 16 | is (scalar <$sock>, "STORED\r\n", "stored key$key"); 17 | } 18 | 19 | my $first_stats = mem_stats($sock, "items"); 20 | my $first_evicted = $first_stats->{"items:31:evicted"}; 21 | # I get 1 eviction on a 32 bit binary, but 4 on a 64 binary.. 22 | # Just check that I have evictions... 23 | isnt ($first_evicted, "0", "check evicted"); 24 | 25 | print $sock "stats reset\r\n"; 26 | is (scalar <$sock>, "RESET\r\n", "Stats reset"); 27 | 28 | my $second_stats = mem_stats($sock, "items"); 29 | my $second_evicted = $second_stats->{"items:31:evicted"}; 30 | is ($second_evicted, "0", "check evicted"); 31 | 32 | for ($key = 40; $key < 80; $key++) { 33 | print $sock "set key$key 0 0 66560\r\n$value\r\n"; 34 | is (scalar <$sock>, "STORED\r\n", "stored key$key"); 35 | } 36 | 37 | my $last_stats = mem_stats($sock, "items"); 38 | my $last_evicted = $last_stats->{"items:31:evicted"}; 39 | is ($last_evicted, "40", "check evicted"); 40 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_260.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # Issue #260 is a terrible bug. 3 | # In order to run this test: 4 | # * checkout 1.4.15 5 | # * change TAIL_REPAIR_TIME from (3 * 3600) to 3 6 | # Now it should cause an assert. Patches can be tested to fix it. 7 | 8 | use strict; 9 | use Test::More; 10 | use FindBin qw($Bin); 11 | use lib "$Bin/lib"; 12 | use MemcachedTest; 13 | 14 | plan skip_all => "Only possible to test #260 under artificial conditions"; 15 | exit 0; 16 | plan tests => 11074; 17 | # assuming max slab is 1M and default mem is 64M 18 | my $server = new_memcached(); 19 | my $sock = $server->sock; 20 | 21 | # create a big value for the largest slab 22 | my $max = 1024 * 1024; 23 | my $big = 'x' x (1024 * 1024 - 250); 24 | 25 | ok(length($big) > 512 * 1024); 26 | ok(length($big) < 1024 * 1024); 27 | 28 | # set the big value 29 | my $len = length($big); 30 | print $sock "set big 0 0 $len\r\n$big\r\n"; 31 | is(scalar <$sock>, "STORED\r\n", "stored big"); 32 | mem_get_is($sock, "big", $big); 33 | 34 | # no evictions yet 35 | my $stats = mem_stats($sock); 36 | is($stats->{"evictions"}, "0", "no evictions to start"); 37 | 38 | # set many big items, enough to get evictions 39 | for (my $i = 0; $i < 100; $i++) { 40 | print $sock "set item_$i 0 0 $len\r\n$big\r\n"; 41 | is(scalar <$sock>, "STORED\r\n", "stored item_$i"); 42 | } 43 | 44 | # some evictions should have happened 45 | my $stats = mem_stats($sock); 46 | my $evictions = int($stats->{"evictions"}); 47 | ok($evictions == 37, "some evictions happened"); 48 | 49 | # the first big value should be gone 50 | mem_get_is($sock, "big", undef); 51 | 52 | # the earliest items should be gone too 53 | for (my $i = 0; $i < $evictions - 1; $i++) { 54 | mem_get_is($sock, "item_$i", undef); 55 | } 56 | 57 | # check that the non-evicted are the right ones 58 | for (my $i = $evictions - 1; $i < $evictions + 4; $i++) { 59 | mem_get_is($sock, "item_$i", $big); 60 | } 61 | 62 | # Now we fill a slab with incrementable items... 63 | for (my $i = 0; $i < 10923; $i++) { 64 | print $sock "set sitem_$i 0 0 1\r\n1\r\n"; 65 | is(scalar <$sock>, "STORED\r\n", "stored sitem_$i"); 66 | } 67 | 68 | my $stats = mem_stats($sock); 69 | my $evictions = int($stats->{"evictions"}); 70 | ok($evictions == 38, "one more eviction happened: $evictions"); 71 | 72 | # That evicted item was the first one we put in. 73 | mem_get_is($sock, "sitem_0", undef); 74 | 75 | sleep 15; 76 | 77 | # Now we increment the item which should be on the tail. 78 | # THIS asserts the memcached-debug binary. 79 | print $sock "incr sitem_1 1\r\n"; 80 | is(scalar <$sock>, "2\r\n", "incremented to two"); 81 | 82 | #my $stats = mem_stats($sock, "slabs"); 83 | #is($stats->{"1:free_chunks"}, 0, "free chunks should still be 0"); 84 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_29.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 4; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | 12 | print $sock "set issue29 0 0 0\r\n\r\n"; 13 | is (scalar <$sock>, "STORED\r\n", "stored issue29"); 14 | 15 | my $first_stats = mem_stats($sock, "slabs"); 16 | my $first_used = $first_stats->{"1:used_chunks"}; 17 | 18 | is(1, $first_used, "Used one"); 19 | 20 | print $sock "set issue29_b 0 0 0\r\n\r\n"; 21 | is (scalar <$sock>, "STORED\r\n", "stored issue29_b"); 22 | 23 | my $second_stats = mem_stats($sock, "slabs"); 24 | my $second_used = $second_stats->{"1:used_chunks"}; 25 | 26 | is(2, $second_used, "Used two") 27 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_3.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 8; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | my $key = "del_key"; 12 | 13 | print $sock "delete $key\r\n"; 14 | is (scalar <$sock>, "NOT_FOUND\r\n", "not found on delete"); 15 | 16 | print $sock "delete $key 10\r\n"; 17 | is (scalar <$sock>, "CLIENT_ERROR bad command line format." 18 | . " Usage: delete [noreply]\r\n", "invalid delete"); 19 | 20 | print $sock "add $key 0 0 1\r\nx\r\n"; 21 | is (scalar <$sock>, "STORED\r\n", "Add before a broken delete."); 22 | 23 | print $sock "delete $key 10 noreply\r\n"; 24 | # Does not reply 25 | # is (scalar <$sock>, "ERROR\r\n", "Even more invalid delete"); 26 | 27 | print $sock "add $key 0 0 1\r\nx\r\n"; 28 | is (scalar <$sock>, "NOT_STORED\r\n", "Failed to add after failed silent delete."); 29 | 30 | print $sock "delete $key noreply\r\n"; 31 | # Will not reply, so let's do a set and check that. 32 | 33 | print $sock "set $key 0 0 1\r\nx\r\n"; 34 | is (scalar <$sock>, "STORED\r\n", "Stored a key"); 35 | 36 | print $sock "delete $key\r\n"; 37 | is (scalar <$sock>, "DELETED\r\n", "Properly deleted"); 38 | 39 | print $sock "set $key 0 0 1\r\nx\r\n"; 40 | is (scalar <$sock>, "STORED\r\n", "Stored a key"); 41 | 42 | print $sock "delete $key noreply\r\n"; 43 | # will not reply, but a subsequent add will succeed 44 | 45 | print $sock "add $key 0 0 1\r\nx\r\n"; 46 | is (scalar <$sock>, "STORED\r\n", "Add succeeded after deletion."); 47 | 48 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_41.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use POSIX qw(ceil); 6 | use Test::More tests => 691; 7 | use FindBin qw($Bin); 8 | use lib "$Bin/lib"; 9 | use MemcachedTest; 10 | 11 | my $server = new_memcached(); 12 | my $sock = $server->sock; 13 | 14 | my $factor = 2; 15 | my $val = "x" x $factor; 16 | my $key = ''; 17 | 18 | # SET items of diverse size to the daemon so it can attempt 19 | # to return a large stats output for slabs 20 | for (my $i=0; $i<69; $i++) { 21 | for (my $j=0; $j<10; $j++) { 22 | $key = "$i:$j"; 23 | print $sock "set key$key 0 0 $factor\r\n$val\r\n"; 24 | is (scalar <$sock>, "STORED\r\n", "stored key$key"); 25 | } 26 | $factor *= 1.2; 27 | $factor = ceil($factor); 28 | $val = "x" x $factor; 29 | } 30 | 31 | # This request will kill the daemon if it has not allocated 32 | # enough memory internally. 33 | my $stats = mem_stats($sock, "slabs"); 34 | 35 | # Verify whether the daemon is still running or not by asking 36 | # it for statistics. 37 | print $sock "version\r\n"; 38 | my $v = scalar <$sock>; 39 | ok(defined $v && length($v), "memcached didn't respond"); 40 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_42.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 11; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached("-o no_modern"); 10 | my $sock = $server->sock; 11 | my $value = "B"x10; 12 | my $key = 0; 13 | my $key_count = 10; 14 | 15 | for ($key = 0; $key < $key_count; $key++) { 16 | print $sock "set key$key 0 0 10\r\n$value\r\n"; 17 | is (scalar <$sock>, "STORED\r\n", "stored key$key"); 18 | } 19 | 20 | my $stats = mem_stats($sock, "slabs"); 21 | my $stats2 = mem_stats($sock, "items"); 22 | my $req = $stats2->{"items:1:mem_requested"}; 23 | my $top = $stats->{"1:chunk_size"} * $key_count; 24 | # unreasonable for the result to be < 500 bytes (min item header is 48), but 25 | # should be less than the maximum potential number. 26 | ok ($req > 500 && $req < $top, "Check allocated size: $req $top"); 27 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_50.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 1; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached('-B binary'); 10 | my $sock = $server->sock; 11 | 12 | $SIG{ALRM} = sub { die "alarm\n" }; 13 | alarm(2); 14 | print $sock "Here's a bunch of garbage that doesn't look like the bin prot."; 15 | my $rv = <$sock>; 16 | ok(1, "Either the above worked and quit, or hung forever."); 17 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_61.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 7; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached("-R 1"); 10 | my $sock = $server->sock; 11 | 12 | print $sock "set foobar 0 0 5\r\nBubba\r\nset foobar 0 0 5\r\nBubba\r\nset foobar 0 0 5\r\nBubba\r\nset foobar 0 0 5\r\nBubba\r\nset foobar 0 0 5\r\nBubba\r\nset foobar 0 0 5\r\nBubba\r\n"; 13 | is (scalar <$sock>, "STORED\r\n", "stored foobar"); 14 | is (scalar <$sock>, "STORED\r\n", "stored foobar"); 15 | is (scalar <$sock>, "STORED\r\n", "stored foobar"); 16 | is (scalar <$sock>, "STORED\r\n", "stored foobar"); 17 | is (scalar <$sock>, "STORED\r\n", "stored foobar"); 18 | is (scalar <$sock>, "STORED\r\n", "stored foobar"); 19 | my $stats = mem_stats($sock); 20 | is ($stats->{"conn_yields"}, "5", "Got a decent number of yields"); 21 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_67.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 24; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | use Carp qw(croak); 9 | use Socket qw(sockaddr_in INADDR_ANY PF_INET SOCK_STREAM); 10 | 11 | use Cwd; 12 | my $builddir = getcwd; 13 | 14 | $ENV{'MEMCACHED_PORT_FILENAME'} = "/tmp/ports.$$"; 15 | 16 | sub read_ports { 17 | my %rv = (); 18 | open(my $f, "/tmp/ports.$$") || die("Can't open ports file."); 19 | while(<$f>) { 20 | my ($type, $port) = split(/:\s+/); 21 | $rv{$type} = $port + 0; 22 | } 23 | unlink "/tmp/ports.$$"; 24 | return %rv; 25 | } 26 | 27 | sub validate_port { 28 | my ($name, $got, $expected) = @_; 29 | # diag "Wanted $expected, got $got"; 30 | if ($expected == -1) { 31 | ok(!defined($got), "$name expected no port, got $got"); 32 | } elsif ($expected == 0) { 33 | ok(defined($got) && $got != 11211, "$name expected random port (got $got)"); 34 | } else { 35 | is($got, $expected, "$name"); 36 | } 37 | } 38 | 39 | sub skip_if_default_addr_in_use(&) { 40 | my ($block) = @_; 41 | 42 | socket(my $socket, PF_INET, SOCK_STREAM, 0) or die $!; 43 | my $addr_in_use = !bind($socket, sockaddr_in(11211, INADDR_ANY)); 44 | close($socket); 45 | 46 | SKIP: { 47 | skip 'Default address is in use. Do you have a running instance?', 2 if $addr_in_use; 48 | return $block->(); 49 | } 50 | } 51 | 52 | sub run_server { 53 | my ($args) = @_; 54 | 55 | my $exe = "$builddir/memcached-debug"; 56 | croak("memcached binary doesn't exist. Haven't run 'make' ?\n") unless -e $exe; 57 | 58 | my $childpid = fork(); 59 | 60 | my $root = ''; 61 | $root = "-u root" if ($< == 0); 62 | 63 | # test build requires more privileges 64 | $args .= " -o relaxed_privileges"; 65 | 66 | my $cmd = "$builddir/timedrun 10 $exe $root $args"; 67 | 68 | unless($childpid) { 69 | exec $cmd; 70 | exit; # NOTREACHED 71 | } 72 | 73 | for (1..20) { 74 | if (-f "/tmp/ports.$$") { 75 | return Memcached::Handle->new(pid => $childpid); 76 | } 77 | select undef, undef, undef, 0.10; 78 | } 79 | croak "Failed to start server."; 80 | } 81 | 82 | sub when { 83 | my ($name, $params, $expected_tcp, $expected_udp) = @_; 84 | 85 | my $server = run_server($params); 86 | my %ports = read_ports(); 87 | 88 | validate_port($name, $ports{'TCP INET'}, $expected_tcp); 89 | validate_port($name, $ports{'UDP INET'}, $expected_udp); 90 | } 91 | 92 | skip_if_default_addr_in_use { when('no arguments', '', 11211, -1) }; 93 | when('specifying tcp port', '-p 11212', 11212, -1); 94 | when('specifying udp port', '-U 11222', 11222, 11222); 95 | when('specifying tcp ephemeral port', '-p -1', 0, -1); 96 | when('specifying udp ephemeral port', '-U -1', 0, 0); 97 | when('tcp port disabled', '-p 0', -1, -1); 98 | skip_if_default_addr_in_use { when('udp port disabled', '-U 0', 11211, -1) }; 99 | when('specifying tcp and udp ports', '-p 11232 -U 11233', 11232, 11233); 100 | when('specifying tcp and disabling udp', '-p 11242 -U 0', 11242, -1); 101 | when('specifying udp and disabling tcp', '-p -1 -U 11252', 0, 11252); 102 | when('specifying tcp and ephemeral udp', '-p 11262 -U -1', 11262, 0); 103 | when('specifying udp and ephemeral tcp', '-p -1 -U 11272', 0, 11272); 104 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_68.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 996; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | 12 | for (my $keyi = 1; $keyi < 250; $keyi++) { 13 | my $key = "x" x $keyi; 14 | print $sock "set $key 0 0 1\r\n9\r\n"; 15 | is (scalar <$sock>, "STORED\r\n", "stored $key"); 16 | mem_get_is($sock, $key, "9"); 17 | print $sock "incr $key 1\r\n"; 18 | is (scalar <$sock>, "10\r\n", "incr $key to 10"); 19 | mem_get_is($sock, $key, "10"); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /memcached-sr/t/issue_70.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 4; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | 12 | print $sock "set issue70 0 0 0\r\n\r\n"; 13 | is (scalar <$sock>, "STORED\r\n", "stored issue70"); 14 | 15 | print $sock "set issue70 0 0 -1\r\n"; 16 | is (scalar <$sock>, "CLIENT_ERROR bad command line format\r\n"); 17 | 18 | print $sock "set issue70 0 0 4294967295\r\n"; 19 | is (scalar <$sock>, "CLIENT_ERROR bad command line format\r\n"); 20 | 21 | print $sock "set issue70 0 0 2147483647\r\nscoobyscoobydoo"; 22 | is (scalar <$sock>, "CLIENT_ERROR bad command line format\r\n"); 23 | -------------------------------------------------------------------------------- /memcached-sr/t/item_size_max.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 7; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | 12 | my $stats = mem_stats($sock, ' settings'); 13 | 14 | # Ensure default still works. 15 | is($stats->{item_size_max}, 1024 * 1024); 16 | $server->stop(); 17 | 18 | # Should die. 19 | eval { 20 | $server = new_memcached('-I 1000'); 21 | }; 22 | ok($@ && $@ =~ m/^Failed/, "Shouldn't start with < 1k item max"); 23 | 24 | eval { 25 | $server = new_memcached('-I 256m'); 26 | }; 27 | ok($@ && $@ =~ m/^Failed/, "Shouldn't start with > 128m item max"); 28 | 29 | # Minimum. 30 | $server = new_memcached('-I 1024 -o slab_chunk_max=1024'); 31 | my $stats = mem_stats($server->sock, ' settings'); 32 | is($stats->{item_size_max}, 1024); 33 | $server->stop(); 34 | 35 | # Reasonable but unreasonable. 36 | $server = new_memcached('-I 2097152'); 37 | my $stats = mem_stats($server->sock, ' settings'); 38 | is($stats->{item_size_max}, 2097152); 39 | $server->stop(); 40 | 41 | # Suffix kilobytes. 42 | $server = new_memcached('-I 512k -o slab_chunk_max=16384'); 43 | my $stats = mem_stats($server->sock, ' settings'); 44 | is($stats->{item_size_max}, 524288); 45 | $server->stop(); 46 | 47 | # Suffix megabytes. 48 | $server = new_memcached('-m 256 -I 32m'); 49 | my $stats = mem_stats($server->sock, ' settings'); 50 | is($stats->{item_size_max}, 33554432); 51 | $server->stop(); 52 | 53 | -------------------------------------------------------------------------------- /memcached-sr/t/line-lengths.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | use strict; 3 | use FindBin qw($Bin); 4 | our @files; 5 | 6 | BEGIN { 7 | chdir "$Bin/.." or die; 8 | @files = ( "doc/protocol.txt" ); 9 | } 10 | 11 | use Test::More tests => scalar(@files); 12 | 13 | foreach my $f (@files) { 14 | open(my $fh, $f) or die("Can't open $f"); 15 | my @long_lines = (); 16 | my $line_number = 0; 17 | while(<$fh>) { 18 | $line_number++; 19 | if(length($_) > 80) { 20 | push(@long_lines, $line_number); 21 | } 22 | } 23 | close($fh); 24 | ok(@long_lines == 0, "$f has a long lines: @long_lines"); 25 | } 26 | -------------------------------------------------------------------------------- /memcached-sr/t/lru-crawler.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More tests => 222; 6 | use FindBin qw($Bin); 7 | use lib "$Bin/lib"; 8 | use MemcachedTest; 9 | 10 | my $server = new_memcached('-m 32 -o no_modern'); 11 | { 12 | my $stats = mem_stats($server->sock, ' settings'); 13 | is($stats->{lru_crawler}, "no"); 14 | } 15 | 16 | my $sock = $server->sock; 17 | 18 | # Fill a slab a bit. 19 | # Some immortal items, some long expiring items, some short expiring items. 20 | # Done so the immortals end up at the tail. 21 | for (1 .. 30) { 22 | print $sock "set ifoo$_ 0 0 2\r\nok\r\n"; 23 | is(scalar <$sock>, "STORED\r\n", "stored key"); 24 | } 25 | for (1 .. 30) { 26 | print $sock "set lfoo$_ 0 3600 2\r\nok\r\n"; 27 | is(scalar <$sock>, "STORED\r\n", "stored key"); 28 | } 29 | for (1 .. 30) { 30 | print $sock "set sfoo$_ 0 1 2\r\nok\r\n"; 31 | is(scalar <$sock>, "STORED\r\n", "stored key"); 32 | } 33 | 34 | { 35 | my $slabs = mem_stats($sock, "slabs"); 36 | is($slabs->{"1:used_chunks"}, 90, "slab1 has 90 used chunks"); 37 | } 38 | 39 | sleep 3; 40 | 41 | print $sock "lru_crawler enable\r\n"; 42 | is(scalar <$sock>, "OK\r\n", "enabled lru crawler"); 43 | { 44 | my $stats = mem_stats($server->sock, ' settings'); 45 | is($stats->{lru_crawler}, "yes"); 46 | } 47 | 48 | print $sock "lru_crawler crawl 1\r\n"; 49 | is(scalar <$sock>, "OK\r\n", "kicked lru crawler"); 50 | while (1) { 51 | my $stats = mem_stats($sock); 52 | last unless $stats->{lru_crawler_running}; 53 | sleep 1; 54 | } 55 | 56 | { 57 | my $slabs = mem_stats($sock, "slabs"); 58 | is($slabs->{"1:used_chunks"}, 60, "slab1 now has 60 used chunks"); 59 | my $items = mem_stats($sock, "items"); 60 | is($items->{"items:1:crawler_reclaimed"}, 30, "slab1 has 30 reclaims"); 61 | } 62 | 63 | # Check that crawler metadump works correctly. 64 | { 65 | print $sock "lru_crawler metadump all\r\n"; 66 | my $count = 0; 67 | while (<$sock>) { 68 | last if /^(\.|END)/; 69 | /^(key=) (\S+).*([^\r\n]+)/; 70 | $count++; 71 | } 72 | is ($count, 60); 73 | } 74 | 75 | for (1 .. 30) { 76 | mem_get_is($sock, "ifoo$_", "ok"); 77 | mem_get_is($sock, "lfoo$_", "ok"); 78 | mem_get_is($sock, "sfoo$_", undef); 79 | } 80 | 81 | print $sock "lru_crawler disable\r\n"; 82 | is(scalar <$sock>, "OK\r\n", "disabled lru crawler"); 83 | { 84 | my $stats = mem_stats($server->sock, ' settings'); 85 | is($stats->{lru_crawler}, "no"); 86 | } 87 | 88 | $server->stop; 89 | 90 | # Test initializing crawler from starttime. 91 | $server = new_memcached('-m 32 -o no_modern,lru_crawler'); 92 | $sock = $server->sock; 93 | 94 | for (1 .. 30) { 95 | print $sock "set sfoo$_ 0 1 2\r\nok\r\n"; 96 | is(scalar <$sock>, "STORED\r\n", "stored key"); 97 | } 98 | 99 | sleep 3; 100 | 101 | print $sock "lru_crawler crawl 1\r\n"; 102 | is(scalar <$sock>, "OK\r\n", "kicked lru crawler"); 103 | while (1) { 104 | my $stats = mem_stats($sock); 105 | last unless $stats->{lru_crawler_running}; 106 | sleep 1; 107 | } 108 | 109 | { 110 | my $slabs = mem_stats($sock, "slabs"); 111 | is($slabs->{"1:used_chunks"}, 0, "slab1 now has 0 used chunks"); 112 | } 113 | -------------------------------------------------------------------------------- /memcached-sr/t/lru.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 149; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | # assuming max slab is 1M and default mem is 64M 10 | my $server = new_memcached('-o no_modern'); 11 | my $sock = $server->sock; 12 | 13 | # create a big value for the largest slab 14 | my $max = 1024 * 1024; 15 | my $big = 'x' x (1024 * 1024 - 250); 16 | 17 | ok(length($big) > 512 * 1024); 18 | ok(length($big) < 1024 * 1024); 19 | 20 | # test that an even bigger value is rejected while we're here 21 | my $too_big = $big . $big . $big; 22 | my $len = length($too_big); 23 | print $sock "set too_big 0 0 $len\r\n$too_big\r\n"; 24 | is(scalar <$sock>, "SERVER_ERROR object too large for cache\r\n", "too_big not stored"); 25 | 26 | # set the big value 27 | my $len = length($big); 28 | print $sock "set big 0 0 $len\r\n$big\r\n"; 29 | is(scalar <$sock>, "STORED\r\n", "stored big"); 30 | mem_get_is($sock, "big", $big); 31 | 32 | # no evictions yet 33 | my $stats = mem_stats($sock); 34 | is($stats->{"evictions"}, "0", "no evictions to start"); 35 | 36 | # set many big items, enough to get evictions 37 | for (my $i = 0; $i < 100; $i++) { 38 | print $sock "set item_$i 0 0 $len\r\n$big\r\n"; 39 | is(scalar <$sock>, "STORED\r\n", "stored item_$i"); 40 | } 41 | 42 | # some evictions should have happened 43 | my $stats = mem_stats($sock); 44 | my $evictions = int($stats->{"evictions"}); 45 | ok($evictions == 37, "some evictions happened"); 46 | 47 | # the first big value should be gone 48 | mem_get_is($sock, "big", undef); 49 | 50 | # the earliest items should be gone too 51 | for (my $i = 0; $i < $evictions - 1; $i++) { 52 | mem_get_is($sock, "item_$i", undef); 53 | } 54 | 55 | # check that the non-evicted are the right ones 56 | for (my $i = $evictions - 1; $i < $evictions + 4; $i++) { 57 | mem_get_is($sock, "item_$i", $big); 58 | } 59 | -------------------------------------------------------------------------------- /memcached-sr/t/malicious-commands.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # These command strings are always expected to be malicious and as such we 4 | # should just hang up on them. 5 | 6 | use strict; 7 | use Test::More tests => 3; 8 | use FindBin qw($Bin); 9 | use lib "$Bin/lib"; 10 | use MemcachedTest; 11 | 12 | my @strs = ( 13 | "GET / HTTP/1.0", 14 | "PUT /asdf/asd/fasdfasdf/sadf HTTP/1.1", 15 | "DELETE HTTP/1.1" 16 | ); 17 | 18 | for my $str (@strs) { 19 | my $server = new_memcached(); 20 | my $sock = $server->sock; 21 | 22 | print $sock "$str\r\n"; 23 | 24 | # Five seconds ought to be enough to get hung up on. 25 | my $oldalarmt = alarm(5); 26 | 27 | # Verify we can't read anything. 28 | my $bytesread = -1; 29 | eval { 30 | local $SIG{'ALRM'} = sub { die "timeout" }; 31 | my $data = ""; 32 | $bytesread = sysread($sock, $data, 24), 33 | }; 34 | is($bytesread, 0, $str); 35 | 36 | # Restore signal stuff. 37 | alarm($oldalarmt); 38 | } 39 | -------------------------------------------------------------------------------- /memcached-sr/t/maxconns.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # NOTE: This test never worked. Memcached would ignore maxconns requests lower 3 | # than the current ulimit. Test needs to be updated. 4 | 5 | use strict; 6 | use warnings; 7 | 8 | use Test::More tests => 11; 9 | 10 | use FindBin qw($Bin); 11 | use lib "$Bin/lib"; 12 | use MemcachedTest; 13 | 14 | 15 | # start up a server with 10 maximum connections 16 | my $server = new_memcached('-c 100'); 17 | my $sock = $server->sock; 18 | my @sockets; 19 | 20 | ok(defined($sock), 'Connection 0'); 21 | push (@sockets, $sock); 22 | 23 | 24 | foreach my $conn (1..10) { 25 | $sock = $server->new_sock; 26 | ok(defined($sock), "Made connection $conn"); 27 | push(@sockets, $sock); 28 | } 29 | -------------------------------------------------------------------------------- /memcached-sr/t/misbehave.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More; 5 | use FindBin qw($Bin); 6 | use Socket qw(MSG_PEEK MSG_DONTWAIT); 7 | use lib "$Bin/lib"; 8 | use MemcachedTest; 9 | 10 | if (!enabled_tls_testing() && supports_drop_priv()) { 11 | plan tests => 1; 12 | } else { 13 | plan skip_all => 'Privilege drop not supported'; 14 | exit 0; 15 | } 16 | 17 | my $server = new_memcached('-o drop_privileges'); 18 | my $sock = $server->sock; 19 | 20 | print $sock "misbehave\r\n"; 21 | sleep(1); 22 | 23 | # check if the socket is dead now 24 | my $buff; 25 | my $ret = recv($sock, $buff, 1, MSG_PEEK | MSG_DONTWAIT); 26 | # ret = 0 means read 0 bytes, which means a closed socket 27 | ok($ret == 0, "did not allow misbehaving"); 28 | 29 | $server->DESTROY(); 30 | -------------------------------------------------------------------------------- /memcached-sr/t/multiversioning.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 13; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | my $sock2 = $server->new_sock; 12 | 13 | ok($sock != $sock2, "have two different connections open"); 14 | 15 | # set large value 16 | my $size = 256 * 1024; # 256 kB 17 | my $bigval = "0123456789abcdef" x ($size / 16); 18 | $bigval =~ s/^0/\[/; $bigval =~ s/f$/\]/; 19 | my $bigval2 = uc($bigval); 20 | 21 | print $sock "set big 0 0 $size\r\n$bigval\r\n"; 22 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 23 | mem_get_is($sock, "big", $bigval, "big value got correctly"); 24 | 25 | print $sock "get big\r\n"; 26 | my $buf; 27 | my $read = 0; 28 | my $to_read = $size / 2; 29 | while ($read < $to_read) { 30 | my $read_bytes = $sock->sysread($buf, 31 | ($to_read - $read > MemcachedTest::MAX_READ_WRITE_SIZE ? 32 | MemcachedTest::MAX_READ_WRITE_SIZE : $to_read - $read), 33 | $read); 34 | last if ($read_bytes <= 0); 35 | $read += $read_bytes; 36 | } 37 | is($read, $size / 2, "read half the answer back"); 38 | like($buf, qr/VALUE big/, "buf has big value header in it"); 39 | like($buf, qr/abcdef/, "buf has some data in it"); 40 | unlike($buf, qr/abcde\]/, "buf doesn't yet close"); 41 | 42 | # sock2 interrupts (maybe sock1 is slow) and deletes stuff: 43 | print $sock2 "delete big\r\n"; 44 | is(scalar <$sock2>, "DELETED\r\n", "deleted big from sock2 while sock1's still reading it"); 45 | mem_get_is($sock2, "big", undef, "nothing from sock2 now. gone from namespace."); 46 | print $sock2 "set big 0 0 $size\r\n$bigval2\r\n"; 47 | is(scalar <$sock2>, "STORED\r\n", "stored big w/ val2"); 48 | mem_get_is($sock2, "big", $bigval2, "big value2 got correctly"); 49 | 50 | # sock1 resumes reading... 51 | $buf .= <$sock>; 52 | $buf .= <$sock>; 53 | like($buf, qr/abcde\]/, "buf now closes"); 54 | 55 | # and if sock1 reads again, it's the uppercase version: 56 | mem_get_is($sock, "big", $bigval2, "big value2 got correctly from sock1"); 57 | -------------------------------------------------------------------------------- /memcached-sr/t/noreply.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 9; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | 10 | my $server = new_memcached(); 11 | my $sock = $server->sock; 12 | 13 | 14 | # Test that commands can take 'noreply' parameter. 15 | print $sock "flush_all noreply\r\n"; 16 | print $sock "flush_all 0 noreply\r\n"; 17 | 18 | print $sock "verbosity 0 noreply\r\n"; 19 | 20 | print $sock "add noreply:foo 0 0 1 noreply\r\n1\r\n"; 21 | mem_get_is($sock, "noreply:foo", "1"); 22 | 23 | print $sock "set noreply:foo 0 0 1 noreply\r\n2\r\n"; 24 | mem_get_is($sock, "noreply:foo", "2"); 25 | 26 | print $sock "replace noreply:foo 0 0 1 noreply\r\n3\r\n"; 27 | mem_get_is($sock, "noreply:foo", "3"); 28 | 29 | print $sock "append noreply:foo 0 0 1 noreply\r\n4\r\n"; 30 | mem_get_is($sock, "noreply:foo", "34"); 31 | 32 | print $sock "prepend noreply:foo 0 0 1 noreply\r\n5\r\n"; 33 | my @result = mem_gets($sock, "noreply:foo"); 34 | ok($result[1] eq "534"); 35 | 36 | print $sock "cas noreply:foo 0 0 1 $result[0] noreply\r\n6\r\n"; 37 | mem_get_is($sock, "noreply:foo", "6"); 38 | 39 | print $sock "incr noreply:foo 3 noreply\r\n"; 40 | mem_get_is($sock, "noreply:foo", "9"); 41 | 42 | print $sock "decr noreply:foo 2 noreply\r\n"; 43 | mem_get_is($sock, "noreply:foo", "7"); 44 | 45 | print $sock "delete noreply:foo noreply\r\n"; 46 | mem_get_is($sock, "noreply:foo"); 47 | -------------------------------------------------------------------------------- /memcached-sr/t/quit.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 1; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | 12 | { 13 | print $sock "quit\r\n"; 14 | 15 | # Five seconds ought to be enough to get hung up on. 16 | my $oldalarmt = alarm(5); 17 | 18 | # Verify we can't read anything. 19 | my $bytesread = -1; 20 | eval { 21 | local $SIG{'ALRM'} = sub { die "timeout" }; 22 | my $data = ""; 23 | $bytesread = sysread($sock, $data, 24), 24 | }; 25 | is($bytesread, 0, "Read after quit."); 26 | 27 | # Restore signal stuff. 28 | alarm($oldalarmt); 29 | } 30 | -------------------------------------------------------------------------------- /memcached-sr/t/refhang.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Test::More; 7 | 8 | use FindBin qw($Bin); 9 | use lib "$Bin/lib"; 10 | use MemcachedTest; 11 | 12 | plan skip_all => 'Test is flaky. Needs special hooks.'; 13 | 14 | plan tests => 127; 15 | 16 | # start up a server with 10 maximum connections 17 | my $server = new_memcached("-m 6"); 18 | my $sock = $server->sock; 19 | my $hangsock = $server->new_sock; 20 | my $hangsock2 = $server->new_sock; 21 | my $value = "B"x66560; 22 | my $key = 0; 23 | 24 | # These aren't set to expire. 25 | my $mget = ''; 26 | for ($key = 0; $key < 120; $key++) { 27 | $mget .= "key$key " if $key < 115; 28 | print $sock "set key$key 0 0 66560\r\n$value\r\n"; 29 | is(scalar <$sock>, "STORED\r\n", "stored key$key"); 30 | } 31 | chop $mget; 32 | 33 | my $stats = mem_stats($sock, "items"); 34 | isnt($stats->{"items:31:evicted"}, "0", "check evicted"); 35 | 36 | my $lrutail_reflocked = $stats->{"items:31:lrutail_reflocked"}; 37 | is($lrutail_reflocked, "0", "check no slab lrutail_reflocked"); 38 | 39 | $stats = mem_stats($sock); 40 | is($stats->{"lrutail_reflocked"}, "0", "check no total lrutail_reflocked"); 41 | 42 | # Don't intend to read the results, need to fill the socket. 43 | # TODO: This test would be smarter if we cranked down the socket buffers 44 | # first? Or perhaps used a unix domain socket. 45 | print $hangsock "get $mget\r\n"; 46 | #sleep 8; 47 | # Now we try a bunch of sets again, and see if they start coming back as OOM's 48 | for ($key = 121; $key < 240; $key++) { 49 | print $sock "set key$key 0 0 66560\r\n$value\r\n"; 50 | my $res = scalar <$sock>; 51 | } 52 | 53 | $stats = mem_stats($sock, "items"); 54 | # Some items will OOM since we only clear a handful per alloc attempt. 55 | ok($stats->{"items:31:outofmemory"} > 0, "some ooms happened"); 56 | ok($stats->{"items:31:outofmemory"} < 20, "fewer than 20 ooms"); 57 | isnt($stats->{"items:31:lrutail_reflocked"}, "0", "nonzero lrutail_reflocked"); 58 | 59 | $stats = mem_stats($sock); 60 | isnt($stats->{"lrutail_reflocked"}, "0", "nonzero total lrutail_reflocked"); 61 | -------------------------------------------------------------------------------- /memcached-sr/t/sasl/memcached.conf: -------------------------------------------------------------------------------- 1 | mech_list: plain cram-md5 2 | log_level: 5 3 | sasldb_path: /tmp/test-memcached.sasldb 4 | -------------------------------------------------------------------------------- /memcached-sr/t/server_crt.pem: -------------------------------------------------------------------------------- 1 | Certificate: 2 | Data: 3 | Version: 3 (0x2) 4 | Serial Number: 1 (0x1) 5 | Signature Algorithm: sha1WithRSAEncryption 6 | Issuer: CN=Test Root Certificate Authority, ST=CA, C=US/emailAddress=root@test.com, O=Test, OU=Test Department 7 | Validity 8 | Not Before: Jan 7 18:25:01 2019 GMT 9 | Not After : Jan 6 18:25:01 2024 GMT 10 | Subject: CN=test.com, ST=CA, C=US/emailAddress=root@test.com, O=Test, OU=Subunit of Test Organization 11 | Subject Public Key Info: 12 | Public Key Algorithm: rsaEncryption 13 | Public-Key: (1024 bit) 14 | Modulus: 15 | 00:ca:76:35:79:91:e8:a2:ee:ef:f4:35:7e:29:85: 16 | 75:90:65:5a:60:f8:a0:d9:ef:68:d1:61:79:69:d7: 17 | e2:7b:f1:67:71:65:50:31:4e:9a:f8:6f:27:e9:05: 18 | 0b:0e:76:95:24:9b:c2:bf:90:e5:6b:45:fd:e3:54: 19 | ac:d5:62:90:4e:37:de:8f:ae:96:f6:b3:57:eb:ad: 20 | b8:44:13:5d:a7:34:76:c1:26:49:91:67:3e:5e:52: 21 | 68:c1:1c:7f:91:c7:9e:01:e2:be:a7:a8:eb:3f:44: 22 | 6d:c7:c5:82:4b:97:d9:3f:c0:51:99:1b:20:df:12: 23 | a3:e6:bb:66:45:6d:b4:e1:07 24 | Exponent: 65537 (0x10001) 25 | X509v3 extensions: 26 | X509v3 Basic Constraints: 27 | CA:FALSE 28 | X509v3 Key Usage: 29 | Digital Signature, Non Repudiation, Key Encipherment 30 | X509v3 Subject Alternative Name: 31 | DNS:test.com, DNS:alt.test.com 32 | Signature Algorithm: sha1WithRSAEncryption 33 | 61:c1:18:b4:04:79:05:0e:b9:79:2f:0e:3f:aa:f1:36:e3:90: 34 | b9:c6:99:25:53:4a:06:64:52:92:29:c5:09:41:a6:16:74:1b: 35 | 3c:4e:81:32:c2:d8:54:e0:1e:08:45:cf:f1:d0:ad:ea:11:1a: 36 | b5:cf:7c:98:8a:dd:c1:01:e4:d0:f5:8e:60:fa:7f:e7:74:2d: 37 | 91:43:81:bd:95:92:41:66:84:8b:8c:70:d7:2f:d4:2f:37:82: 38 | 8f:9a:ef:c0:7d:c5:56:56:92:7a:00:b6:30:65:37:4c:6c:7a: 39 | ba:cc:e2:dc:73:e9:f5:2c:3c:3e:31:67:ee:3d:b7:78:96:89: 40 | ba:be:4f:85:a2:a8:83:3e:53:20:f0:bf:29:50:dc:23:38:58: 41 | d8:33:f5:7b:4a:12:df:2b:34:4c:1c:f1:76:6b:86:95:74:43: 42 | 29:f7:68:f0:ca:04:08:89:ac:97:7d:05:14:a0:ca:81:56:5c: 43 | dd:c3:56:a3:53:01:0a:01:5c:55:b4:39:10:1b:be:47:19:58: 44 | a1:f2:e6:0c:08:95:b0:35:4e:6c:81:6d:b9:cf:0e:5c:70:ff: 45 | f3:b4:a7:95:69:1a:58:b7:ac:cc:2c:79:47:7e:20:17:cc:36: 46 | be:2c:10:11:31:28:63:dd:6f:8d:8d:e9:11:ea:ca:fc:10:0a: 47 | e0:ae:53:db 48 | -----BEGIN CERTIFICATE----- 49 | MIIDQjCCAiqgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBizEoMCYGA1UEAwwfVGVz 50 | dCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eTELMAkGA1UECAwCQ0ExCzAJBgNV 51 | BAYTAlVTMRwwGgYJKoZIhvcNAQkBFg1yb290QHRlc3QuY29tMQ0wCwYDVQQKDARU 52 | ZXN0MRgwFgYDVQQLDA9UZXN0IERlcGFydG1lbnQwHhcNMTkwMTA3MTgyNTAxWhcN 53 | MjQwMTA2MTgyNTAxWjCBgTERMA8GA1UEAwwIdGVzdC5jb20xCzAJBgNVBAgMAkNB 54 | MQswCQYDVQQGEwJVUzEcMBoGCSqGSIb3DQEJARYNcm9vdEB0ZXN0LmNvbTENMAsG 55 | A1UECgwEVGVzdDElMCMGA1UECwwcU3VidW5pdCBvZiBUZXN0IE9yZ2FuaXphdGlv 56 | bjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAynY1eZHoou7v9DV+KYV1kGVa 57 | YPig2e9o0WF5adfie/FncWVQMU6a+G8n6QULDnaVJJvCv5Dla0X941Ss1WKQTjfe 58 | j66W9rNX6624RBNdpzR2wSZJkWc+XlJowRx/kceeAeK+p6jrP0Rtx8WCS5fZP8BR 59 | mRsg3xKj5rtmRW204QcCAwEAAaM9MDswCQYDVR0TBAIwADALBgNVHQ8EBAMCBeAw 60 | IQYDVR0RBBowGIIIdGVzdC5jb22CDGFsdC50ZXN0LmNvbTANBgkqhkiG9w0BAQUF 61 | AAOCAQEAYcEYtAR5BQ65eS8OP6rxNuOQucaZJVNKBmRSkinFCUGmFnQbPE6BMsLY 62 | VOAeCEXP8dCt6hEatc98mIrdwQHk0PWOYPp/53QtkUOBvZWSQWaEi4xw1y/ULzeC 63 | j5rvwH3FVlaSegC2MGU3TGx6uszi3HPp9Sw8PjFn7j23eJaJur5PhaKogz5TIPC/ 64 | KVDcIzhY2DP1e0oS3ys0TBzxdmuGlXRDKfdo8MoECImsl30FFKDKgVZc3cNWo1MB 65 | CgFcVbQ5EBu+RxlYofLmDAiVsDVObIFtuc8OXHD/87SnlWkaWLeszCx5R34gF8w2 66 | viwQETEoY91vjY3pEerK/BAK4K5T2w== 67 | -----END CERTIFICATE----- 68 | -------------------------------------------------------------------------------- /memcached-sr/t/server_key.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICXQIBAAKBgQDKdjV5keii7u/0NX4phXWQZVpg+KDZ72jRYXlp1+J78WdxZVAx 3 | Tpr4byfpBQsOdpUkm8K/kOVrRf3jVKzVYpBON96Prpb2s1frrbhEE12nNHbBJkmR 4 | Zz5eUmjBHH+Rx54B4r6nqOs/RG3HxYJLl9k/wFGZGyDfEqPmu2ZFbbThBwIDAQAB 5 | AoGBAItN/ItSVrRNHTN13wHovzSEWERiriJl9UQkAmtOTJqlRlyiriPPBxgrO1W8 6 | z5e7BfGzbrNqmkBOX1uctnL4J3tA7xFO6OnquDCLXhLc49mw+zxkcDP5ta1ROeiV 7 | kIm8rSsvh8ks7StA17m5910rNfn5/IRHK6dC+G4FK7qLfCiRAkEA5Szy22sFeE4D 8 | OM/wmCHpoOc0qA5k0FeyvnfGFKcAsVZ2+b/MPI2/KbB0uY/PWj43H6h9fEqMGVf6 9 | J7Ukas1N2QJBAOIozZjzfs3PQvKHMzOG3mQt+qSjsDKiEq/cPMIRPXYX5pS0+2Gz 10 | mtUaikI+Nk5hekXqA2i+4uis9UhCzm+W+d8CQQCEo/ZPrmp1DdnpiNh8hKw+l3Kv 11 | jd0lhIyMlrALhfjtqtijhjHEHlo0289DEwv09CtdZFx0koTxqiy7zKiuM/NJAkBZ 12 | S2sB/QIQGMmCIMeijJm6TD0uTEMBeuSN8xM6PLxbqEwuYtbuWI/FnFkClrWydOJm 13 | QGNgNB47aC7gfSAtBxtZAkBiCJcoVmXkm3rS7scUgCHrNhKH0G0nJbqjgfj57I31 14 | rCw34N6L+fyUozJQCBYdECyI1xG2eajqrMmnVZ046cjF 15 | -----END RSA PRIVATE KEY----- 16 | -------------------------------------------------------------------------------- /memcached-sr/t/slabhang.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | 6 | use Test::More; 7 | 8 | use FindBin qw($Bin); 9 | use lib "$Bin/lib"; 10 | use MemcachedTest; 11 | 12 | plan skip_all => 'Test is flaky. Needs special hooks.'; 13 | 14 | plan tests => 74; 15 | 16 | # start up a server with 10 maximum connections 17 | my $server = new_memcached("-m 16 -o modern"); 18 | my $sock = $server->sock; 19 | my $hangsock = $server->new_sock; 20 | my $value = "B"x260144; 21 | my $key = 0; 22 | 23 | # disable the normal automover. 24 | print $sock "slabs automove 0\r\n"; 25 | is(scalar <$sock>, "OK\r\n", "automover disabled"); 26 | 27 | # These aren't set to expire. 28 | my $mget = ''; 29 | for ($key = 0; $key < 70; $key++) { 30 | $mget .= "key$key "; 31 | print $sock "set key$key 0 0 260144\r\n$value\r\n"; 32 | is(scalar <$sock>, "STORED\r\n", "stored key$key"); 33 | } 34 | chop $mget; 35 | 36 | # Don't intend to read the results, need to fill the socket. 37 | print $hangsock "get $mget\r\n"; 38 | #sleep 8; 39 | my $stats = mem_stats($sock, "slabs"); 40 | my $source = 0; 41 | for my $key (keys %$stats) { 42 | if ($key =~ m/^(\d+):total_pages/) { 43 | my $sid = $1; 44 | if ($stats->{$key} > 10) { 45 | $source = $sid; 46 | last; 47 | } 48 | } 49 | } 50 | isnt($source, 0, "found the source slab: $source"); 51 | 52 | my $busy; 53 | my $tomove = 4; 54 | my $reassign = "slabs reassign $source 1\r\n"; 55 | while ($tomove) { 56 | $busy = 0; 57 | print $sock $reassign; 58 | my $res = scalar <$sock>; 59 | while ($res =~ m/^BUSY/) { 60 | if ($hangsock && $busy > 5) { 61 | # unjam the pipeline 62 | $hangsock->close; 63 | } 64 | last if ($busy > 10); 65 | sleep 1; 66 | $busy++; 67 | print $sock $reassign; 68 | $res = scalar <$sock>; 69 | } 70 | last if ($busy > 10); 71 | $tomove--; 72 | } 73 | 74 | ok($busy <= 10, "didn't time out moving pages"); 75 | 76 | $stats = mem_stats($sock); 77 | isnt($stats->{"slab_reassign_busy_deletes"}, "0", "deleted some busy items"); 78 | -------------------------------------------------------------------------------- /memcached-sr/t/slabs_reassign.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More tests => 130; 6 | use FindBin qw($Bin); 7 | use lib "$Bin/lib"; 8 | use MemcachedTest; 9 | 10 | # Enable manual slab reassign, cap at 6 slabs 11 | my $server = new_memcached('-o slab_reassign -m 4'); 12 | my $stats = mem_stats($server->sock, ' settings'); 13 | is($stats->{slab_reassign}, "yes"); 14 | 15 | my $sock = $server->sock; 16 | 17 | # Fill a largeish slab until it evicts (honors the -m 6) 18 | my $bigdata = 'x' x 70000; # slab 31 19 | for (1 .. 60) { 20 | print $sock "set bfoo$_ 0 0 70000\r\n", $bigdata, "\r\n"; 21 | is(scalar <$sock>, "STORED\r\n", "stored key"); 22 | } 23 | 24 | # Fill a smaller slab until it evicts 25 | my $smalldata = 'y' x 20000; # slab 25 26 | for (1 .. 60) { 27 | print $sock "set sfoo$_ 0 0 20000\r\n", $smalldata, "\r\n"; 28 | is(scalar <$sock>, "STORED\r\n", "stored key"); 29 | } 30 | 31 | my $items_before = mem_stats($sock, "items"); 32 | isnt($items_before->{"items:31:evicted"}, 0, "slab 31 evicted is nonzero"); 33 | isnt($items_before->{"items:25:evicted"}, 0, "slab 25 evicted is nonzero"); 34 | 35 | my $slabs_before = mem_stats($sock, "slabs"); 36 | # Move a large slab to the smaller slab 37 | print $sock "slabs reassign 31 25\r\n"; 38 | is(scalar <$sock>, "OK\r\n", "slab rebalancer started"); 39 | 40 | # Still working out how/if to signal the thread. For now, just sleep. 41 | sleep 2; 42 | 43 | # Check that stats counters increased 44 | my $slabs_after = mem_stats($sock, "slabs"); 45 | $stats = mem_stats($sock); 46 | 47 | isnt($stats->{slabs_moved}, 0, "slabs moved is nonzero"); 48 | 49 | # Check that slab stats reflect the change 50 | ok($slabs_before->{"31:total_pages"} != $slabs_after->{"31:total_pages"}, 51 | "slab 31 pagecount changed"); 52 | ok($slabs_before->{"25:total_pages"} != $slabs_after->{"25:total_pages"}, 53 | "slab 25 pagecount changed"); 54 | 55 | # Try to move another slab, see that you can move two in a row 56 | print $sock "slabs reassign 31 25\r\n"; 57 | like(scalar <$sock>, qr/^OK/, "Cannot re-run against class with empty space"); 58 | 59 | # Try to move a page backwards. Should complain that source class isn't "safe" 60 | # to move from. 61 | # TODO: Wait until the above command completes, then try to move it back? 62 | # Seems pointless... 63 | #print $sock "slabs reassign 25 31\r\n"; 64 | #like(scalar <$sock>, qr/^UNSAFE/, "Cannot move an unsafe slab back"); 65 | 66 | # Try to insert items into both slabs 67 | print $sock "set bfoo51 0 0 70000\r\n", $bigdata, "\r\n"; 68 | is(scalar <$sock>, "STORED\r\n", "stored key"); 69 | 70 | print $sock "set sfoo51 0 0 20000\r\n", $smalldata, "\r\n"; 71 | is(scalar <$sock>, "STORED\r\n", "stored key"); 72 | 73 | # Do need to come up with better automated tests for this. 74 | -------------------------------------------------------------------------------- /memcached-sr/t/ssl_cert_refresh.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use File::Copy; 6 | use Test::More; 7 | use FindBin qw($Bin); 8 | use lib "$Bin/lib"; 9 | use MemcachedTest; 10 | 11 | if (!enabled_tls_testing()) { 12 | plan skip_all => 'SSL testing is not enabled'; 13 | exit 0; 14 | } 15 | 16 | my $ca_cert = "t/" . MemcachedTest::CA_CRT; 17 | my $cert = "t/". MemcachedTest::SRV_CRT; 18 | my $key = "t/". MemcachedTest::SRV_KEY; 19 | my $ca_cert_back = "t/ca_cert_back"; 20 | my $cert_back = "t/cert_back"; 21 | my $key_back = "t/pkey_back"; 22 | my $new_cert_key = "t/server.pem"; 23 | my $default_crt_ou = "OU=Subunit of Test Organization"; 24 | 25 | my $server = new_memcached("-o ssl_ca_cert=$ca_cert"); 26 | my $stats = mem_stats($server->sock); 27 | my $pid = $stats->{pid}; 28 | my $sock = $server->sock; 29 | 30 | # This connection should return the default server certificate 31 | # memcached was started with. 32 | my $cert_details =$sock->dump_peer_certificate(); 33 | $cert_details =~ m/(OU=([^\/\n]*))/; 34 | is($1, $default_crt_ou, 'Got the default cert'); 35 | 36 | # Swap a new certificate with a key 37 | copy($ca_cert, $ca_cert_back) or die "CA cert backup failed: $!"; 38 | copy($cert, $cert_back) or die "Cert backup failed: $!"; 39 | copy($key, $key_back) or die "Key backup failed: $!"; 40 | copy($new_cert_key, $ca_cert) or die "New CA cert copy failed: $!"; 41 | copy($new_cert_key, $cert) or die "New Cert copy failed: $!"; 42 | copy($new_cert_key, $key) or die "New key copy failed: $!"; 43 | 44 | # Ask server to refresh certificates 45 | print $sock "refresh_certs\r\n"; 46 | is(scalar <$sock>, "OK\r\n", "refreshed certificates"); 47 | 48 | # New connections should use the new certificate 49 | $cert_details = $server->new_sock->dump_peer_certificate(); 50 | $cert_details =~ m/(OU=([^\/]*))/; 51 | is($1, 'OU=FOR TESTING PURPOSES ONLY','Got the new cert'); 52 | # Old connection should use the previous certificate 53 | $cert_details = $sock->dump_peer_certificate(); 54 | $cert_details =~ m/(OU=([^\/\n]*))/; 55 | is($1, $default_crt_ou, 'Old connection still has the old cert'); 56 | 57 | # Just sleep a while to test the time_since_server_cert_refresh as it's counted 58 | # in seconds. 59 | sleep 2; 60 | $stats = mem_stats($sock); 61 | 62 | # Restore and ensure previous certificate is back for new connections. 63 | move($ca_cert_back, $ca_cert) or die "CA cert restore failed: $!"; 64 | move($cert_back, $cert) or die "Cert restore failed: $!"; 65 | move($key_back, $key) or die "Key restore failed: $!"; 66 | print $sock "refresh_certs\r\n"; 67 | is(scalar <$sock>, "OK\r\n", "refreshed certificates"); 68 | 69 | 70 | $cert_details = $server->new_sock->dump_peer_certificate(); 71 | $cert_details =~ m/(OU=([^\/\n]*))/; 72 | is($1, $default_crt_ou, 'Got the old cert back'); 73 | 74 | my $stats_after = mem_stats($sock); 75 | 76 | # We should see last refresh time is reset; hence the new 77 | # time_since_server_cert_refresh should be less. 78 | cmp_ok($stats_after->{time_since_server_cert_refresh}, '<', 79 | $stats->{time_since_server_cert_refresh}, 'Certs refreshed'); 80 | 81 | done_testing(); 82 | -------------------------------------------------------------------------------- /memcached-sr/t/ssl_ports.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | use FindBin qw($Bin); 7 | use lib "$Bin/lib"; 8 | use MemcachedTest; 9 | 10 | 11 | if (!enabled_tls_testing()) { 12 | plan skip_all => 'SSL testing is not enabled'; 13 | exit 0; 14 | } 15 | 16 | my $tcp_port = free_port(); 17 | my $ssl_port = free_port(); 18 | 19 | my $server = new_memcached("-l notls:127.0.0.1:$tcp_port,127.0.0.1:$ssl_port", $ssl_port); 20 | my $sock = $server->sock; 21 | 22 | # Make sure we can talk over SSL 23 | print $sock "set foo:123 0 0 16\r\nfoo set over SSL\r\n"; 24 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 25 | 26 | 27 | #.. and TCP 28 | my $tcp_sock = IO::Socket::INET->new(PeerAddr => "127.0.0.1:$tcp_port"); 29 | mem_get_is($tcp_sock, "foo:123", "foo set over SSL"); 30 | 31 | done_testing() 32 | -------------------------------------------------------------------------------- /memcached-sr/t/ssl_settings.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | use FindBin qw($Bin); 7 | use lib "$Bin/lib"; 8 | use MemcachedTest; 9 | use Cwd; 10 | 11 | if (!enabled_tls_testing()) { 12 | plan skip_all => 'SSL testing is not enabled'; 13 | exit 0; 14 | } 15 | 16 | my $server = new_memcached(); 17 | my $settings = mem_stats($server->sock, ' settings'); 18 | 19 | my $cert = getcwd ."/t/". MemcachedTest::SRV_CRT; 20 | my $key = getcwd ."/t/". MemcachedTest::SRV_KEY; 21 | 22 | is($settings->{'ssl_enabled'}, 'yes'); 23 | is($settings->{'ssl_chain_cert'}, $cert); 24 | is($settings->{'ssl_key'}, $key); 25 | is($settings->{'ssl_verify_mode'}, 0); 26 | is($settings->{'ssl_keyformat'}, 1); 27 | is($settings->{'ssl_ciphers'}, 'NULL'); 28 | is($settings->{'ssl_ca_cert'}, 'NULL'); 29 | is($settings->{'ssl_wbuf_size'}, 16384); 30 | 31 | $server->DESTROY(); 32 | $server = new_memcached("-o ssl_wbuf_size=64"); 33 | $settings = mem_stats($server->sock, ' settings'); 34 | is($settings->{'ssl_wbuf_size'},65536); 35 | 36 | done_testing(); 37 | -------------------------------------------------------------------------------- /memcached-sr/t/ssl_verify_modes.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use warnings; 5 | use Test::More; 6 | use FindBin qw($Bin); 7 | use lib "$Bin/lib"; 8 | use MemcachedTest; 9 | use Cwd; 10 | 11 | if (!enabled_tls_testing()) { 12 | plan skip_all => 'SSL testing is not enabled'; 13 | exit 0; 14 | } 15 | 16 | my $ca_crt = getcwd() . "/t/" . MemcachedTest::CA_CRT; 17 | my $server = new_memcached("-o ssl_verify_mode=2 -o ssl_ca_cert=$ca_crt"); 18 | # just using stats to make sure everything is working fine. 19 | my $stats = mem_stats($server->sock); 20 | is($stats->{accepting_conns}, 1, "client cert is verified"); 21 | 22 | done_testing(); 23 | -------------------------------------------------------------------------------- /memcached-sr/t/stats-conns.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 12; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | ## First make sure we report UNIX-domain sockets correctly 10 | 11 | my $filename = "/tmp/memcachetest$$"; 12 | 13 | my $server = new_memcached("-s $filename"); 14 | my $sock = $server->sock; 15 | my $stats_sock = $server->new_sock; 16 | 17 | ok(-S $filename, "creating unix domain socket $filename"); 18 | 19 | print $sock "set foo 0 0 6\r\n"; 20 | sleep(1); # so we can test secs_since_last_cmd is nonzero 21 | print $stats_sock "stats conns\r\n"; 22 | 23 | my $stats; 24 | while (<$stats_sock>) { 25 | last if /^(\.|END)/; 26 | $stats .= $_; 27 | } 28 | 29 | like($stats, qr/STAT \d+:addr /); 30 | $stats =~ m/STAT (\d+):addr unix:(.*[^\r\n])/g; 31 | my $listen_fd = $1; 32 | my $socket_path = $2; 33 | # getsockname(2) doesn't return socket path on GNU/Hurd (and maybe others) 34 | SKIP: { 35 | skip "socket path checking on GNU kernel", 1 if ($^O eq 'gnu'); 36 | is($socket_path, $filename, "unix domain socket path reported correctly"); 37 | }; 38 | $stats =~ m/STAT (\d+):state conn_listening\r\n/g; 39 | is($1, $listen_fd, "listen socket fd reported correctly"); 40 | 41 | like($stats, qr/STAT \d+:state conn_nread/, 42 | "one client is sending data"); 43 | like($stats, qr/STAT \d+:state conn_parse_cmd/, 44 | "one client is in command processing"); 45 | like($stats, qr/STAT \d+:secs_since_last_cmd [1-9]\r/, 46 | "nonzero secs_since_last_cmd"); 47 | like($stats, qr/STAT \d+:listen_addr unix:\/tmp\/memcachetest\d+\r/, 48 | "found listen_addr for the UNIX-domain socket"); 49 | 50 | $server->stop; 51 | unlink($filename); 52 | 53 | ## Now look at TCP 54 | 55 | $server = new_memcached("-l 0.0.0.0"); 56 | $sock = $server->sock; 57 | $stats_sock = $server->new_sock; 58 | 59 | print $sock "set foo 0 0 6\r\n"; 60 | print $stats_sock "stats conns\r\n"; 61 | 62 | $stats = ''; 63 | while (<$stats_sock>) { 64 | last if /^(\.|END)/; 65 | $stats .= $_; 66 | } 67 | 68 | like($stats, qr/STAT \d+:state conn_listen/, "there is a listen socket"); 69 | $stats =~ m/STAT \d+:addr udp:0.0.0.0:(\d+)/; 70 | is($1, $server->udpport, "udp port number is correct"); 71 | $stats =~ m/STAT \d+:addr tcp:0.0.0.0:(\d+)/; 72 | print STDERR "PORT: ", $server->port, "\n"; 73 | is($1, $server->port, "tcp port number is correct"); 74 | 75 | $stats =~ m/STAT \d+:listen_addr tcp:0.0.0.0:(\d+)/; 76 | is($1, $server->port, "listen_addr is correct for the tcp port"); 77 | -------------------------------------------------------------------------------- /memcached-sr/t/stats-detail.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 24; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $server = new_memcached(); 10 | my $sock = $server->sock; 11 | my $expire; 12 | 13 | print $sock "stats detail dump\r\n"; 14 | is(scalar <$sock>, "END\r\n", "verified empty stats at start"); 15 | 16 | print $sock "stats detail on\r\n"; 17 | is(scalar <$sock>, "OK\r\n", "detail collection turned on"); 18 | 19 | print $sock "set foo:123 0 0 6\r\nfooval\r\n"; 20 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 21 | 22 | print $sock "stats detail dump\r\n"; 23 | is(scalar <$sock>, "PREFIX foo get 0 hit 0 set 1 del 0\r\n", "details after set"); 24 | is(scalar <$sock>, "END\r\n", "end of details"); 25 | 26 | mem_get_is($sock, "foo:123", "fooval"); 27 | print $sock "stats detail dump\r\n"; 28 | is(scalar <$sock>, "PREFIX foo get 1 hit 1 set 1 del 0\r\n", "details after get with hit"); 29 | is(scalar <$sock>, "END\r\n", "end of details"); 30 | 31 | mem_get_is($sock, "foo:124", undef); 32 | 33 | print $sock "stats detail dump\r\n"; 34 | is(scalar <$sock>, "PREFIX foo get 2 hit 1 set 1 del 0\r\n", "details after get without hit"); 35 | is(scalar <$sock>, "END\r\n", "end of details"); 36 | 37 | print $sock "delete foo:125\r\n"; 38 | is(scalar <$sock>, "NOT_FOUND\r\n", "sent delete command"); 39 | 40 | print $sock "stats detail dump\r\n"; 41 | is(scalar <$sock>, "PREFIX foo get 2 hit 1 set 1 del 1\r\n", "details after delete"); 42 | is(scalar <$sock>, "END\r\n", "end of details"); 43 | 44 | print $sock "stats reset\r\n"; 45 | is(scalar <$sock>, "RESET\r\n", "stats cleared"); 46 | 47 | print $sock "stats detail dump\r\n"; 48 | is(scalar <$sock>, "END\r\n", "empty stats after clear"); 49 | 50 | mem_get_is($sock, "foo:123", "fooval"); 51 | print $sock "stats detail dump\r\n"; 52 | is(scalar <$sock>, "PREFIX foo get 1 hit 1 set 0 del 0\r\n", "details after clear and get"); 53 | is(scalar <$sock>, "END\r\n", "end of details"); 54 | 55 | print $sock "stats detail off\r\n"; 56 | is(scalar <$sock>, "OK\r\n", "detail collection turned off"); 57 | 58 | mem_get_is($sock, "foo:124", undef); 59 | 60 | mem_get_is($sock, "foo:123", "fooval"); 61 | print $sock "stats detail dump\r\n"; 62 | is(scalar <$sock>, "PREFIX foo get 1 hit 1 set 0 del 0\r\n", "details after stats turned off"); 63 | is(scalar <$sock>, "END\r\n", "end of details"); 64 | -------------------------------------------------------------------------------- /memcached-sr/t/stress-memcached.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # 3 | 4 | use strict; 5 | use lib '../../api/perl/lib'; 6 | use Cache::Memcached; 7 | use Time::HiRes qw(time); 8 | 9 | unless (@ARGV == 2) { 10 | die "Usage: stress-memcached.pl ip:port threads\n"; 11 | } 12 | 13 | my $host = shift; 14 | my $threads = shift; 15 | 16 | my $memc = new Cache::Memcached; 17 | $memc->set_servers([$host]); 18 | 19 | unless ($memc->set("foo", "bar") && 20 | $memc->get("foo") eq "bar") { 21 | die "memcached not running at $host ?\n"; 22 | } 23 | $memc->disconnect_all(); 24 | 25 | 26 | my $running = 0; 27 | while (1) { 28 | if ($running < $threads) { 29 | my $cpid = fork(); 30 | if ($cpid) { 31 | $running++; 32 | #print "Launched $cpid. Running $running threads.\n"; 33 | } else { 34 | stress(); 35 | exit 0; 36 | } 37 | } else { 38 | wait(); 39 | $running--; 40 | } 41 | } 42 | 43 | sub stress { 44 | undef $memc; 45 | $memc = new Cache::Memcached; 46 | $memc->set_servers([$host]); 47 | 48 | my ($t1, $t2); 49 | my $start = sub { $t1 = time(); }; 50 | my $stop = sub { 51 | my $op = shift; 52 | $t2 = time(); 53 | my $td = sprintf("%0.3f", $t2 - $t1); 54 | if ($td > 0.25) { print "Took $td seconds for: $op\n"; } 55 | }; 56 | 57 | my $max = rand(50); 58 | my $sets = 0; 59 | 60 | for (my $i = 0; $i < $max; $i++) { 61 | my $key = key($i); 62 | my $set = $memc->set($key, $key); 63 | $sets++ if $set; 64 | } 65 | 66 | for (1..int(rand(500))) { 67 | my $rand = int(rand($max)); 68 | my $key = key($rand); 69 | my $meth = int(rand(3)); 70 | my $exp = int(rand(3)); 71 | undef $exp unless $exp; 72 | $start->(); 73 | if ($meth == 0) { 74 | $memc->add($key, $key, $exp); 75 | $stop->("add"); 76 | } elsif ($meth == 1) { 77 | $memc->delete($key); 78 | $stop->("delete"); 79 | } else { 80 | $memc->set($key, $key, $exp); 81 | $stop->("set"); 82 | } 83 | $rand = int(rand($max)); 84 | $key = key($rand); 85 | $start->(); 86 | my $v = $memc->get($key); 87 | $stop->("get"); 88 | if ($v && $v ne $key) { die "Bogus: $v for key $rand\n"; } 89 | } 90 | 91 | $start->(); 92 | my $multi = $memc->get_multi(map { key(int(rand($max))) } (1..$max)); 93 | $stop->("get_multi"); 94 | } 95 | 96 | sub key { 97 | my $n = shift; 98 | $_ = sprintf("%04d", $n); 99 | if ($n % 2) { $_ .= "a"x20; } 100 | $_; 101 | } 102 | -------------------------------------------------------------------------------- /memcached-sr/t/touch.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 4; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | 10 | my $server = new_memcached(); 11 | my $sock = $server->sock; 12 | 13 | # set foo (and should get it) 14 | print $sock "set foo 0 2 6\r\nfooval\r\n"; 15 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 16 | mem_get_is($sock, "foo", "fooval"); 17 | 18 | # touch it 19 | print $sock "touch foo 10\r\n"; 20 | is(scalar <$sock>, "TOUCHED\r\n", "touched foo"); 21 | 22 | sleep 2; 23 | mem_get_is($sock, "foo", "fooval"); 24 | -------------------------------------------------------------------------------- /memcached-sr/t/unixsocket.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 3; 5 | use FindBin qw($Bin); 6 | use lib "$Bin/lib"; 7 | use MemcachedTest; 8 | 9 | my $filename = "/tmp/memcachetest$$"; 10 | 11 | my $server = new_memcached("-s $filename"); 12 | my $sock = $server->sock; 13 | 14 | ok(-S $filename, "creating unix domain socket $filename"); 15 | 16 | # set foo (and should get it) 17 | print $sock "set foo 0 0 6\r\nfooval\r\n"; 18 | 19 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 20 | mem_get_is($sock, "foo", "fooval"); 21 | 22 | unlink($filename); 23 | 24 | ## Just some basic stuff for now... 25 | -------------------------------------------------------------------------------- /memcached-sr/t/watcher_connid.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # Test for adding connection id to the output when watching fetchers 3 | # and mutations. 4 | # Note that this test relies on the order of connection establishments. This 5 | # could be improved if there's a way for a client to retrieve its connection id. 6 | use strict; 7 | use warnings; 8 | use Socket qw/SO_RCVBUF/; 9 | 10 | use Test::More tests => 4; 11 | use FindBin qw($Bin); 12 | use lib "$Bin/lib"; 13 | use MemcachedTest; 14 | 15 | my $server = new_memcached('-m 60 -o watcher_logbuf_size=8'); 16 | my $client_first = $server->sock; 17 | 18 | my $stats; 19 | 20 | # get the first client's connection id 21 | print $client_first "stats conns\r\n"; 22 | while (<$client_first>) { 23 | last if /^(\.|END)/; 24 | $stats = $_; 25 | } 26 | my $cfd_first =(split(':', $stats))[0]; 27 | $cfd_first =~ s/[^0-9]//g; 28 | 29 | # start watching fetchers and mutations 30 | my $watcher = $server->new_sock; 31 | print $watcher "watch fetchers mutations\n"; 32 | my $res = <$watcher>; 33 | is($res, "OK\r\n", "watching enabled for fetchers and mutations"); 34 | 35 | # first client does a set, which will result in a get and a set 36 | print $client_first "set foo 0 0 5 noreply\r\nhello\r\n"; 37 | 38 | # ensure client's connection id is correct 39 | $res = <$watcher>; 40 | print $res; 41 | like($res, qr/ts=\d+\.\d+\ gid=\d+ type=item_get key=foo status=not_found clsid=\d+ cfd=$cfd_first/, 42 | "Saw a miss with the connection id $cfd_first"); 43 | $res = <$watcher>; 44 | print $res; 45 | like($res, qr/ts=\d+\.\d+\ gid=\d+ type=item_store key=foo status=stored cmd=set ttl=\d+ clsid=\d+ cfd=$cfd_first/, 46 | "Saw a set with the connection id $cfd_first"); 47 | 48 | # get the second client's connection id 49 | my $client_second = $server->new_sock; 50 | print $client_second "stats conns\r\n"; 51 | while (<$client_second>) { 52 | last if /^(\.|END)/; 53 | $stats = $_; 54 | } 55 | my $cfd_second =(split(':', $stats))[0]; 56 | $cfd_second =~ s/[^0-9]//g; 57 | 58 | # second client does a get 59 | print $client_second "get foo\r\n"; 60 | 61 | # now we should see second client's connection id 62 | $res = <$watcher>; 63 | print $res; 64 | like($res, qr/ts=\d+\.\d+\ gid=\d+ type=item_get key=foo status=found clsid=\d+ cfd=$cfd_second/, 65 | "Saw a get with the connection id $cfd_second"); 66 | 67 | -------------------------------------------------------------------------------- /memcached-sr/t/whitespace.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | use strict; 3 | use FindBin qw($Bin); 4 | our @files; 5 | 6 | BEGIN { 7 | chdir "$Bin/.." or die; 8 | 9 | my @exempted = qw(Makefile.am ChangeLog doc/Makefile.am README README.md compile_commands.json); 10 | push(@exempted, glob("doc/*.xml")); 11 | push(@exempted, glob("doc/*.full")); 12 | push(@exempted, glob("doc/xml2rfc/*.xsl")); 13 | push(@exempted, glob("m4/*backport*m4")); 14 | push(@exempted, glob("*.orig")); 15 | push(@exempted, glob(".*.swp")); 16 | my %exempted_hash = map { $_ => 1 } @exempted; 17 | 18 | my @stuff = split /\0/, `git ls-files -z -c -m -o --exclude-standard`; 19 | @files = grep { ! $exempted_hash{$_} } @stuff; 20 | 21 | # We won't find any files if git isn't installed. If git isn't 22 | # installed, they're probably not doing any useful development, or 23 | # at the very least am will clean up whitespace when we receive 24 | # their patch. 25 | unless (@files) { 26 | use Test::More; 27 | plan skip_all => "Skipping tests probably because you don't have git."; 28 | exit 0; 29 | } 30 | } 31 | 32 | use Test::More tests => scalar(@files); 33 | 34 | foreach my $f (@files) { 35 | open(my $fh, $f) or die "Cannot open file $f: $!"; 36 | my $before = do { local $/; <$fh>; }; 37 | close ($fh); 38 | my $after = $before; 39 | $after =~ s/\t/ /g; 40 | $after =~ s/ +$//mg; 41 | $after .= "\n" unless $after =~ /\n$/; 42 | ok ($after eq $before, "$f (see devtools/clean-whitespace.pl)"); 43 | } 44 | -------------------------------------------------------------------------------- /memcached-sr/timedrun.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | volatile sig_atomic_t caught_sig = 0; 11 | 12 | static void signal_handler(int which) 13 | { 14 | caught_sig = which; 15 | } 16 | 17 | static int wait_for_process(pid_t pid) 18 | { 19 | int rv = EX_SOFTWARE; 20 | int status = 0; 21 | int i = 0; 22 | struct sigaction sig_handler; 23 | 24 | sig_handler.sa_handler = signal_handler; 25 | sig_handler.sa_flags = 0; 26 | 27 | sigaction(SIGALRM, &sig_handler, NULL); 28 | sigaction(SIGHUP, &sig_handler, NULL); 29 | sigaction(SIGINT, &sig_handler, NULL); 30 | sigaction(SIGUSR1, &sig_handler, NULL); 31 | sigaction(SIGTERM, &sig_handler, NULL); 32 | sigaction(SIGPIPE, &sig_handler, NULL); 33 | 34 | /* Loop forever waiting for the process to quit */ 35 | for (i = 0; ;i++) { 36 | pid_t p = waitpid(pid, &status, 0); 37 | if (p == pid) { 38 | /* child exited. Let's get out of here */ 39 | rv = WIFEXITED(status) ? 40 | WEXITSTATUS(status) : 41 | (0x80 | WTERMSIG(status)); 42 | break; 43 | } else { 44 | int sig = 0; 45 | switch (i) { 46 | case 0: 47 | /* On the first iteration, pass the signal through */ 48 | sig = caught_sig > 0 ? caught_sig : SIGTERM; 49 | if (caught_sig == SIGALRM) { 50 | fprintf(stderr, "Timeout.. killing the process\n"); 51 | } 52 | break; 53 | case 1: 54 | sig = SIGTERM; 55 | break; 56 | default: 57 | sig = SIGKILL; 58 | break; 59 | } 60 | if (kill(pid, sig) < 0) { 61 | /* Kill failed. Must have lost the process. :/ */ 62 | perror("lost child when trying to kill"); 63 | } 64 | /* Wait up to 5 seconds for the pid */ 65 | alarm(5); 66 | } 67 | } 68 | return rv; 69 | } 70 | 71 | static int spawn_and_wait(char **argv) 72 | { 73 | int rv = EX_SOFTWARE; 74 | pid_t pid = fork(); 75 | 76 | switch (pid) { 77 | case -1: 78 | perror("fork"); 79 | rv = EX_OSERR; 80 | break; /* NOTREACHED */ 81 | case 0: 82 | execvp(argv[0], argv); 83 | perror("exec"); 84 | rv = EX_SOFTWARE; 85 | break; /* NOTREACHED */ 86 | default: 87 | rv = wait_for_process(pid); 88 | } 89 | return rv; 90 | } 91 | 92 | int main(int argc, char **argv) 93 | { 94 | int naptime = 0; 95 | assert(argc > 2); 96 | 97 | naptime = atoi(argv[1]); 98 | assert(naptime > 0 && naptime < 1800); 99 | 100 | alarm(naptime); 101 | 102 | return spawn_and_wait(argv+2); 103 | } 104 | -------------------------------------------------------------------------------- /memcached-sr/tls.h: -------------------------------------------------------------------------------- 1 | #ifndef TLS_H 2 | #define TLS_H 3 | 4 | void SSL_LOCK(void); 5 | void SSL_UNLOCK(void); 6 | ssize_t ssl_read(conn *c, void *buf, size_t count); 7 | ssize_t ssl_sendmsg(conn *c, struct msghdr *msg, int flags); 8 | ssize_t ssl_write(conn *c, void *buf, size_t count); 9 | 10 | int ssl_init(void); 11 | bool refresh_certs(char **errmsg); 12 | void ssl_callback(const SSL *s, int where, int ret); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /memcached-sr/trace.h: -------------------------------------------------------------------------------- 1 | #ifndef TRACE_H 2 | #define TRACE_H 3 | 4 | #ifdef ENABLE_DTRACE 5 | #include "memcached_dtrace.h" 6 | #else 7 | #define MEMCACHED_ASSOC_DELETE(arg0, arg1) 8 | #define MEMCACHED_ASSOC_DELETE_ENABLED() (0) 9 | #define MEMCACHED_ASSOC_FIND(arg0, arg1, arg2) 10 | #define MEMCACHED_ASSOC_FIND_ENABLED() (0) 11 | #define MEMCACHED_ASSOC_INSERT(arg0, arg1) 12 | #define MEMCACHED_ASSOC_INSERT_ENABLED() (0) 13 | #define MEMCACHED_COMMAND_ADD(arg0, arg1, arg2, arg3, arg4) 14 | #define MEMCACHED_COMMAND_ADD_ENABLED() (0) 15 | #define MEMCACHED_COMMAND_APPEND(arg0, arg1, arg2, arg3, arg4) 16 | #define MEMCACHED_COMMAND_APPEND_ENABLED() (0) 17 | #define MEMCACHED_COMMAND_CAS(arg0, arg1, arg2, arg3, arg4) 18 | #define MEMCACHED_COMMAND_CAS_ENABLED() (0) 19 | #define MEMCACHED_COMMAND_DECR(arg0, arg1, arg2, arg3) 20 | #define MEMCACHED_COMMAND_DECR_ENABLED() (0) 21 | #define MEMCACHED_COMMAND_DELETE(arg0, arg1, arg2) 22 | #define MEMCACHED_COMMAND_DELETE_ENABLED() (0) 23 | #define MEMCACHED_COMMAND_GET(arg0, arg1, arg2, arg3, arg4) 24 | #define MEMCACHED_COMMAND_GET_ENABLED() (0) 25 | #define MEMCACHED_COMMAND_TOUCH(arg0, arg1, arg2, arg3, arg4) 26 | #define MEMCACHED_COMMAND_TOUCH_ENABLED() (0) 27 | #define MEMCACHED_COMMAND_INCR(arg0, arg1, arg2, arg3) 28 | #define MEMCACHED_COMMAND_INCR_ENABLED() (0) 29 | #define MEMCACHED_COMMAND_PREPEND(arg0, arg1, arg2, arg3, arg4) 30 | #define MEMCACHED_COMMAND_PREPEND_ENABLED() (0) 31 | #define MEMCACHED_COMMAND_REPLACE(arg0, arg1, arg2, arg3, arg4) 32 | #define MEMCACHED_COMMAND_REPLACE_ENABLED() (0) 33 | #define MEMCACHED_COMMAND_SET(arg0, arg1, arg2, arg3, arg4) 34 | #define MEMCACHED_COMMAND_SET_ENABLED() (0) 35 | #define MEMCACHED_CONN_ALLOCATE(arg0) 36 | #define MEMCACHED_CONN_ALLOCATE_ENABLED() (0) 37 | #define MEMCACHED_CONN_CREATE(arg0) 38 | #define MEMCACHED_CONN_CREATE_ENABLED() (0) 39 | #define MEMCACHED_CONN_DESTROY(arg0) 40 | #define MEMCACHED_CONN_DESTROY_ENABLED() (0) 41 | #define MEMCACHED_CONN_DISPATCH(arg0, arg1) 42 | #define MEMCACHED_CONN_DISPATCH_ENABLED() (0) 43 | #define MEMCACHED_CONN_RELEASE(arg0) 44 | #define MEMCACHED_CONN_RELEASE_ENABLED() (0) 45 | #define MEMCACHED_ITEM_LINK(arg0, arg1, arg2) 46 | #define MEMCACHED_ITEM_LINK_ENABLED() (0) 47 | #define MEMCACHED_ITEM_REMOVE(arg0, arg1, arg2) 48 | #define MEMCACHED_ITEM_REMOVE_ENABLED() (0) 49 | #define MEMCACHED_ITEM_REPLACE(arg0, arg1, arg2, arg3, arg4, arg5) 50 | #define MEMCACHED_ITEM_REPLACE_ENABLED() (0) 51 | #define MEMCACHED_ITEM_UNLINK(arg0, arg1, arg2) 52 | #define MEMCACHED_ITEM_UNLINK_ENABLED() (0) 53 | #define MEMCACHED_ITEM_UPDATE(arg0, arg1, arg2) 54 | #define MEMCACHED_ITEM_UPDATE_ENABLED() (0) 55 | #define MEMCACHED_PROCESS_COMMAND_END(arg0, arg1, arg2) 56 | #define MEMCACHED_PROCESS_COMMAND_END_ENABLED() (0) 57 | #define MEMCACHED_PROCESS_COMMAND_START(arg0, arg1, arg2) 58 | #define MEMCACHED_PROCESS_COMMAND_START_ENABLED() (0) 59 | #define MEMCACHED_SLABS_ALLOCATE(arg0, arg1, arg2, arg3) 60 | #define MEMCACHED_SLABS_ALLOCATE_ENABLED() (0) 61 | #define MEMCACHED_SLABS_ALLOCATE_FAILED(arg0, arg1) 62 | #define MEMCACHED_SLABS_ALLOCATE_FAILED_ENABLED() (0) 63 | #define MEMCACHED_SLABS_FREE(arg0, arg1, arg2) 64 | #define MEMCACHED_SLABS_FREE_ENABLED() (0) 65 | #define MEMCACHED_SLABS_SLABCLASS_ALLOCATE(arg0) 66 | #define MEMCACHED_SLABS_SLABCLASS_ALLOCATE_ENABLED() (0) 67 | #define MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED(arg0) 68 | #define MEMCACHED_SLABS_SLABCLASS_ALLOCATE_FAILED_ENABLED() (0) 69 | #endif 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /memcached-sr/util.h: -------------------------------------------------------------------------------- 1 | /* fast-enough functions for uriencoding strings. */ 2 | void uriencode_init(void); 3 | bool uriencode(const char *src, char *dst, const size_t srclen, const size_t dstlen); 4 | 5 | /* 6 | * Wrappers around strtoull/strtoll that are safer and easier to 7 | * use. For tests and assumptions, see internal_tests.c. 8 | * 9 | * str a NULL-terminated base decimal 10 unsigned integer 10 | * out out parameter, if conversion succeeded 11 | * 12 | * returns true if conversion succeeded. 13 | */ 14 | bool safe_strtoull(const char *str, uint64_t *out); 15 | bool safe_strtoull_hex(const char *str, uint64_t *out); 16 | bool safe_strtoll(const char *str, int64_t *out); 17 | bool safe_strtoul(const char *str, uint32_t *out); 18 | bool safe_strtol(const char *str, int32_t *out); 19 | bool safe_strtod(const char *str, double *out); 20 | bool safe_strcpy(char *dst, const char *src, const size_t dstmax); 21 | 22 | #ifndef HAVE_HTONLL 23 | extern uint64_t htonll(uint64_t); 24 | extern uint64_t ntohll(uint64_t); 25 | #endif 26 | 27 | #ifdef __GCC 28 | # define __gcc_attribute__ __attribute__ 29 | #else 30 | # define __gcc_attribute__(x) 31 | #endif 32 | 33 | /** 34 | * Vararg variant of perror that makes for more useful error messages 35 | * when reporting with parameters. 36 | * 37 | * @param fmt a printf format 38 | */ 39 | void vperror(const char *fmt, ...) 40 | __gcc_attribute__ ((format (printf, 1, 2))); 41 | -------------------------------------------------------------------------------- /memcached-sr/version.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | # If you think this is stupid/overkill, blame dormando 3 | 4 | use warnings; 5 | use strict; 6 | 7 | my $version = `git describe`; 8 | chomp $version; 9 | # Test the various versions. 10 | #my $version = 'foob'; 11 | #my $version = '1.4.2-30-gf966dba'; 12 | #my $version = '1.4.3-rc1'; 13 | #my $version = '1.4.3'; 14 | unless ($version =~ m/^\d+\.\d+\.\d+/) { 15 | write_file('version.m4', "m4_define([VERSION_NUMBER], [UNKNOWN])\n"); 16 | exit; 17 | } 18 | 19 | $version =~ s/-/_/g; 20 | write_file('version.m4', "m4_define([VERSION_NUMBER], [$version])\n"); 21 | my ($VERSION, $FULLVERSION, $RELEASE); 22 | 23 | if ($version =~ m/^(\d+\.\d+\.\d+)_rc(\d+)$/) { 24 | $VERSION = $1; 25 | $FULLVERSION = $version; 26 | $RELEASE = '0.1.rc' . $2; 27 | } elsif ($version =~ m/^(\d+\.\d+\.\d+)_(.+)$/) { 28 | $VERSION = $1; 29 | $FULLVERSION = $version; 30 | $RELEASE = '1.' . $2; 31 | } elsif ($version =~ m/^(\d+\.\d+\.\d+)$/) { 32 | $VERSION = $1; 33 | $FULLVERSION = $version; 34 | $RELEASE = '1'; 35 | } 36 | 37 | my $spec = read_file('memcached.spec.in'); 38 | $spec =~ s/\@VERSION\@/$VERSION/gm; 39 | $spec =~ s/\@FULLVERSION\@/$FULLVERSION/gm; 40 | $spec =~ s/\@RELEASE\@/$RELEASE/gm; 41 | 42 | write_file('memcached.spec', $spec); 43 | 44 | sub write_file { 45 | my $file = shift; 46 | my $data = shift; 47 | open(my $fh, "> $file") or die "Can't open $file: $!"; 48 | print $fh $data; 49 | close($fh); 50 | } 51 | 52 | sub read_file { 53 | my $file = shift; 54 | local $/ = undef; 55 | open(my $fh, "< $file") or die "Can't open $file: $!"; 56 | my $data = <$fh>; 57 | close($fh); 58 | return $data; 59 | } 60 | -------------------------------------------------------------------------------- /memcached-sr/version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if git describe | sed s/-/_/g > version.num.tmp 4 | then 5 | mv version.num.tmp version.num 6 | echo "m4_define([VERSION_NUMBER], [`tr -d '\n' < version.num`])" \ 7 | > version.m4 8 | sed s/@VERSION@/`cat version.num`/ < memcached.spec.in > memcached.spec 9 | else 10 | rm version.num.tmp 11 | fi 12 | --------------------------------------------------------------------------------