├── .gitignore ├── .gitmodules ├── .shipit ├── AUTHORS ├── CMakeLists.txt ├── COPYING ├── ChangeLog ├── Doxyfile ├── HACKING ├── LICENSE ├── NEWS ├── README ├── TODO ├── TODO.moxi ├── conflate ├── adhoc_commands.c ├── conflate.c ├── conflate_internal.h ├── kvpair.c ├── logging.c ├── persist.c ├── rest.c ├── rest.h ├── util.c └── xmpp.c ├── debian ├── changelog.in ├── compat ├── control ├── copyright ├── dirs ├── docs ├── moxi.default ├── moxi.examples ├── moxi.init └── rules ├── devtools ├── bench_noreply.pl ├── clean-whitespace.pl └── svn-tarballs.pl ├── doc ├── CONTRIBUTORS ├── Doxyfile ├── Makefile.am ├── building-moxi-packages.txt ├── memory_management.txt ├── moxi.1 ├── moxi │ └── configuration.org ├── protocol.txt ├── readme.txt ├── threads.txt └── xml2rfc │ ├── reference.RFC.0768.xml │ ├── rfc2629-noinc.xsl │ ├── rfc2629-other.ent │ ├── rfc2629-refchk.xsl │ ├── rfc2629-xhtml.ent │ └── rfc2629.dtd ├── include ├── libconflate │ └── conflate.h └── libvbucket │ ├── vbucket.h │ └── visibility.h ├── libmemcached ├── .gitignore ├── AUTHORS ├── CMakeLists.txt ├── COPYING ├── ChangeLog ├── NEWS ├── README ├── README.FIRST ├── README.win32 ├── THANKS ├── TODO ├── libhashkit │ ├── algorithm.c │ ├── algorithm.h │ ├── behavior.c │ ├── behavior.h │ ├── common.h │ ├── configure.h │ ├── configure.h.in │ ├── crc32.c │ ├── digest.c │ ├── digest.h │ ├── fnv.c │ ├── function.c │ ├── function.h │ ├── hashkit.c │ ├── hashkit.h │ ├── jenkins.c │ ├── ketama.c │ ├── md5.c │ ├── one_at_a_time.c │ ├── strerror.c │ ├── strerror.h │ ├── types.h │ └── visibility.h ├── libmemcached │ ├── allocators.c │ ├── allocators.h │ ├── analyze.c │ ├── analyze.h │ ├── auto.c │ ├── auto.h │ ├── behavior.c │ ├── behavior.h │ ├── byteorder.c │ ├── byteorder.h │ ├── callback.c │ ├── callback.h │ ├── common.h │ ├── configure.h │ ├── configure.h.in │ ├── connect.c │ ├── constants.h │ ├── delete.c │ ├── delete.h │ ├── do.c │ ├── do.h │ ├── dump.c │ ├── dump.h │ ├── exception.hpp │ ├── fetch.c │ ├── fetch.h │ ├── flush.c │ ├── flush.h │ ├── flush_buffers.c │ ├── flush_buffers.h │ ├── get.c │ ├── get.h │ ├── hash.c │ ├── hash.h │ ├── hosts.c │ ├── internal.h │ ├── io.c │ ├── io.h │ ├── key.c │ ├── libmemcached_probes.d │ ├── libmemcached_probes.h │ ├── memcached.c │ ├── memcached.h │ ├── memcached.hpp │ ├── memcached │ │ ├── README.txt │ │ └── protocol_binary.h │ ├── memcached_util.h │ ├── parse.c │ ├── parse.h │ ├── platform.h │ ├── protocol_handler.h │ ├── purge.c │ ├── quit.c │ ├── quit.h │ ├── response.c │ ├── response.h │ ├── result.c │ ├── result.h │ ├── sasl.h │ ├── server.c │ ├── server.h │ ├── server_list.c │ ├── server_list.h │ ├── stats.c │ ├── stats.h │ ├── storage.c │ ├── storage.h │ ├── strerror.c │ ├── strerror.h │ ├── string.c │ ├── string.h │ ├── types.h │ ├── util.h │ ├── verbosity.c │ ├── verbosity.h │ ├── version.c │ ├── version.h │ ├── visibility.h │ ├── watchpoint.h │ └── win32.c ├── libmemcached_config.h.in ├── poll │ ├── poll.c │ └── poll.h └── win32 │ ├── inttypes.h │ ├── stdbool.h │ ├── stdint.h │ ├── strings.h │ ├── sys │ └── time.h │ ├── unistd.h │ └── wrappers.h ├── memcached.spec.in ├── scripts ├── dtrace-profile.d ├── dtrace-syscalls.d ├── examples │ ├── moxi.conf.direct │ └── moxi.conf.service ├── memcached-init ├── memcached-tool ├── memcached.sysv ├── moxi-init.rhat.in ├── rpm │ ├── build-fc-rpm │ └── moxi.spec.in └── start-memcached ├── src ├── agent.h ├── agent_config.c ├── agent_ping.c ├── agent_stats.c ├── assoc.c ├── assoc.h ├── cache.c ├── cache.h ├── check_moxi.c ├── check_moxi_agent.c ├── check_util.c ├── check_work.c ├── config.cmake.h ├── cproxy.c ├── cproxy.h ├── cproxy_config.c ├── cproxy_front.c ├── cproxy_multiget.c ├── cproxy_protocol_a.c ├── cproxy_protocol_a2a.c ├── cproxy_protocol_a2b.c ├── cproxy_protocol_b.c ├── cproxy_protocol_b2b.c ├── cproxy_stats.c ├── daemon.c ├── genhash.c ├── genhash.h ├── genhash_int.h ├── globals.c ├── hash.c ├── hash.h ├── htgram.c ├── htgram.h ├── items.c ├── items.h ├── log.c ├── log.h ├── matcher.c ├── matcher.h ├── mcs.c ├── mcs.h ├── memcached.c ├── memcached.h ├── murmur_hash.c ├── protocol_binary.h ├── redirects.c ├── redirects.h ├── slabs.c ├── slabs.h ├── solaris_priv.c ├── stats.c ├── stats.h ├── stdin_check.c ├── stdin_check.h ├── strsep.c ├── testapp.c ├── thread.c ├── timedrun.c ├── trace.h ├── util.c ├── util.h ├── work.c └── work.h ├── t ├── 00-startup.t ├── 64bit.t ├── binary-get.t ├── binary.t ├── bogus-commands.t ├── cas.t ├── daemonize.t ├── dash-M.t ├── expirations.t ├── flags.t ├── flush-all.t ├── getset.t ├── incrdecr.t ├── issue-MB-2649.sh ├── issue-MB-2660.sh ├── issue-MB-2689.sh ├── issue-MB-2811.sh ├── issue-MB-2825.sh ├── issue-MB-2972.sh ├── issue-MB-2980.sh ├── issue-MB-3076.sh ├── issue-MB-3113.sh ├── issue-MB-3575.sh ├── issue-conn-close.sh ├── issue_14.t ├── issue_22.t ├── issue_29.t ├── issue_41.t ├── issue_42.t ├── issue_50.t ├── issue_61.t ├── issue_70.t ├── ketama_rest_mixed.cfg ├── ketama_rest_one.cfg ├── lib │ └── MemcachedTest.pm ├── line-lengths.t ├── lru.t ├── maxconns.t ├── mc_bin_client.py ├── memcacheConstants.py ├── moxi.pl ├── moxi_all.pl ├── moxi_mock.cfg ├── moxi_mock.pl ├── moxi_mock_a2a.py ├── moxi_mock_a2b.py ├── moxi_mock_auth.py ├── moxi_mock_b2b.py ├── moxi_mock_server.py ├── moxi_multitenancy.py ├── moxi_multitenancy_default.py ├── moxi_multitenancy_rest.cfg ├── moxi_multitenancy_rest_default.cfg ├── moxi_one.pl ├── multiversioning.t ├── noreply.t ├── rest_mock.rb ├── slab-reassign.t ├── stats-detail.t ├── stats.t ├── stress-memcached.pl ├── udp.t ├── unixsocket.t ├── vbucket1.cfg ├── vbucket2.cfg ├── vbucket_rest1.cfg ├── vbucket_rest2.cfg └── whitespace.t ├── tests ├── conflate │ ├── check_alarm.c │ ├── check_kvpair.c │ ├── test_common.c │ └── test_common.h ├── moxi │ ├── htgram_test.c │ └── sizes.c └── vbucket │ ├── config │ ├── ketama-eight-nodes │ ├── ketama-eight-nodes.md5sum │ ├── ketama-ordered-eight-nodes │ ├── ketama-ordered-eight-nodes.md5sum │ ├── regression-bug2112 │ ├── testapp-config │ ├── testapp-config-couch-api-base │ ├── testapp-config-diff1 │ ├── testapp-config-diff2 │ ├── testapp-config-diff3 │ ├── testapp-config-flat │ ├── testapp-config-in-envelope │ ├── testapp-config-in-envelope-fft │ ├── testapp-config-in-envelope2 │ ├── testapp-config-user-password1 │ ├── testapp-config-user-password2 │ ├── testapp-config-wrong-num-vbuckets │ ├── testapp-config-zero-num-vbuckets │ └── vbucket-eight-nodes │ ├── macros.h │ ├── regression.c │ ├── testapp.c │ └── testketama.c └── vbucket ├── crc32.c ├── hash.h ├── ketama.c ├── rfc1321 ├── global.h ├── md5.h └── md5c.c ├── vbucket.c ├── vbucketkeygen.c └── vbuckettool.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.[ao] 2 | *.dll 3 | *.dylib 4 | *.so 5 | *.exe 6 | *.gcda 7 | *.gcno 8 | *.gcov 9 | *.tcov 10 | *.dll 11 | *.dll.* 12 | *.exp 13 | *.ilk 14 | *.lib 15 | *.pdb 16 | *.exe.* 17 | *~ 18 | .buildbot/* 19 | .deps 20 | .libs 21 | /GPATH 22 | /GRTAGS 23 | /GSYMS 24 | /GTAGS 25 | /ID 26 | /check_moxi 27 | /check_moxi_agent 28 | /check_util 29 | /check_work 30 | /config/test-driver 31 | /debian/changelog 32 | /doc/doxy 33 | /m4/version.m4 34 | /memcached.spec 35 | /scripts/rpm/moxi.spec 36 | /sizes 37 | /t/*.pyc 38 | /t/check_moxi_agent.cfg 39 | /testapp 40 | /timedrun 41 | /tmp 42 | /version.num 43 | INSTALL 44 | Makefile 45 | Makefile.in 46 | TAGS 47 | a.out* 48 | aclocal.m4 49 | autom4te.cache 50 | compile 51 | config.cache 52 | config.guess 53 | config.h 54 | config.h.in 55 | config.log 56 | config.status 57 | config.sub 58 | configure 59 | cscope.out 60 | depcomp 61 | doc/protocol-binary-range.txt 62 | doc/protocol-binary.txt 63 | htgram_test 64 | install-sh 65 | libmemcached-*/libmemcached/*.la 66 | libmemcached-*/libmemcached/*.lo 67 | libmemcached-*/libmemcached/.libs/ 68 | libmemcached-*/libmemcached/libmemcached_config.h 69 | /memcached 70 | /memcached-*.tar.gz 71 | /memcached-debug 72 | /memcached-debug.profile 73 | /memcached_dtrace.h 74 | /missing 75 | /moxi 76 | /moxi-*.tar.gz 77 | /moxi-debug 78 | /moxi-debug.profile 79 | /moxi_*.tar.gz 80 | /stamp-h1 81 | /stamp-h2 82 | /tags 83 | /CMakeFiles/ 84 | /CMakeCache.txt 85 | /CTestTestfile.cmake 86 | /cmake_install.cmake 87 | /moxi_htgram_test 88 | /moxi_sizes 89 | /moxi.exe.embed.manifest 90 | /moxi.exe.embed.manifest.res 91 | /moxi.exe.intermediate.manifest 92 | /moxi.exe.resource.txt 93 | /moxi.ilk 94 | /moxi.pdb 95 | /moxi_htgram_test.exe.embed.manifest 96 | /moxi_htgram_test.exe.embed.manifest.res 97 | /moxi_htgram_test.exe.intermediate.manifest 98 | /moxi_htgram_test.exe.resource.txt 99 | /moxi_htgram_test.ilk 100 | /moxi_htgram_test.pdb 101 | /moxi_sizes.exe.embed.manifest 102 | /moxi_sizes.exe.embed.manifest.res 103 | /moxi_sizes.exe.intermediate.manifest 104 | /moxi_sizes.exe.resource.txt 105 | /moxi_sizes.ilk 106 | /moxi_sizes.pdb 107 | /tests_check_kvpair 108 | /vbucket_regression 109 | /vbucket_testapp 110 | /vbucket_testketama 111 | /vbucketkeygen 112 | /vbuckettool 113 | Testing 114 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libconflate"] 2 | path = libconflate 3 | url = git://github.com/northscale/libconflate.git 4 | -------------------------------------------------------------------------------- /.shipit: -------------------------------------------------------------------------------- 1 | steps = FindVersion, ChangeVersion, CheckChangeLog, DistTest, Commit, Tag, MakeDist, AddToSVNDir 2 | 3 | AddToSVNDir.dir = ../website/dist 4 | svn.tagpattern = %v 5 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Anatoly Vorobey 2 | Brad Fitzpatrick 3 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /HACKING: -------------------------------------------------------------------------------- 1 | * Hacking Moxi 2 | 3 | * Prerequisites 4 | 5 | - autoconf 6 | - automake 7 | - autotools 8 | - libevent 9 | - check 10 | 11 | * Getting Started 12 | 13 | After checking out a git repository, you must first run autogen.sh 14 | once in order to create the configure script. 15 | 16 | Next, run the configure script and start doing builds. 17 | 18 | * Setting up Git 19 | 20 | Though not required, there are a couple of things you can add to git 21 | to help development. 22 | 23 | ** Pre Commit Hook 24 | 25 | The pre-commit hook can be used to ensure that your tree passes tests 26 | before allowing a commit. To do so, add the following to 27 | .git/hooks/pre-commit (which must be executable): 28 | 29 | #!/bin/sh 30 | make test 31 | 32 | ** Post Commit Hook 33 | 34 | Because the version number changes on each commit, it's good to use a 35 | post commit hook to update the version number after each commit so as 36 | to keep the reporting accurate. To do so, add the following to 37 | .git/hooks/post-commit (which must be executable) 38 | 39 | #!/bin/sh 40 | ./version.sh 41 | 42 | * Running tests 43 | 44 | It has been noted that tests hang on some OSs. After investigation, 45 | this is due to those OSs using a default shell which doesn't kill off 46 | the child process from a kill. This has been noted on Ubuntu with 47 | the shell dash. To run tests convert the default shell to bash with 48 | dpkg-reconfigure. 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | http://www.danga.com/memcached/news.bml 2 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | * bug as shown with netcat (w/ small 16 byte object reproduces) 2 | 3 | >>I've done the following script to check that memcached has a key in it's 4 | >>inside, and thus know that it's working correctly: 5 | >>echo -e "get is_ok\r\nquit\r\n" | netcat $host $ip 6 | >> 7 | >>and I find that sometimes it returns the VALUE in it's inside, but other 8 | >>not. 9 | 10 | * namespaces 11 | 12 | * binary get protocol 13 | 14 | * refresh/touch command. 15 | 16 | * finer granularity of time for flush_all/delete, or generation number. 17 | 18 | * slab class reassignment still buggy and can crash. once that's 19 | stable, server should re-assign pages every 60 seconds or so 20 | to keep all classes roughly equal. [Update: fixed now?, but 21 | not heavily tested. Future: make slab classes, with per-class 22 | cleaners functions.] 23 | 24 | * calendar queue for early expirations of items, so they don't push 25 | out other objects with infinite expirations. 26 | 27 | * curr_items never decreases? mailing list report. 28 | 29 | * memcached to listen on more than one IP. mailing list request. 30 | -------------------------------------------------------------------------------- /conflate/conflate.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "conflate_internal.h" 7 | #include "rest.h" 8 | 9 | /* Randomly generated by a fair dice roll */ 10 | #define INITIALIZATION_MAGIC 142285011 11 | #define HTTP_PREFIX "HTTP:" 12 | 13 | void run_conflate(void *); 14 | 15 | 16 | conflate_config_t* dup_conf(conflate_config_t c) { 17 | conflate_config_t *rv = calloc(sizeof(conflate_config_t), 1); 18 | cb_assert(rv); 19 | 20 | rv->jid = safe_strdup(c.jid); 21 | rv->pass = safe_strdup(c.pass); 22 | if (c.host) { 23 | rv->host = safe_strdup(c.host); 24 | } 25 | rv->software = safe_strdup(c.software); 26 | rv->version = safe_strdup(c.version); 27 | rv->save_path = safe_strdup(c.save_path); 28 | rv->userdata = c.userdata; 29 | rv->log = c.log; 30 | rv->new_config = c.new_config; 31 | 32 | rv->initialization_marker = (void*)INITIALIZATION_MAGIC; 33 | 34 | return rv; 35 | } 36 | 37 | void init_conflate(conflate_config_t *conf) 38 | { 39 | cb_assert(conf); 40 | memset(conf, 0x00, sizeof(conflate_config_t)); 41 | conf->log = conflate_stderr_logger; 42 | conf->initialization_marker = (void*)INITIALIZATION_MAGIC; 43 | } 44 | 45 | bool start_conflate(conflate_config_t conf) { 46 | conflate_handle_t *handle; 47 | void (*run_func)(void*) = NULL; 48 | 49 | /* Don't start if we don't believe initialization has occurred. */ 50 | if (conf.initialization_marker != (void*)INITIALIZATION_MAGIC) { 51 | cb_assert(conf.initialization_marker == (void*)INITIALIZATION_MAGIC); 52 | return false; 53 | } 54 | 55 | handle = calloc(1, sizeof(conflate_handle_t)); 56 | cb_assert(handle); 57 | 58 | if (strncmp(HTTP_PREFIX, conf.host, strlen(HTTP_PREFIX))) { 59 | run_func = &run_rest_conflate; 60 | } else { 61 | run_func = &run_conflate; 62 | conflate_init_commands(); 63 | } 64 | 65 | handle->conf = dup_conf(conf); 66 | 67 | if (cb_create_thread(&handle->thread, run_func, handle, 1) == 0) { 68 | return true; 69 | } else { 70 | perror("Failed to create thread"); 71 | } 72 | 73 | return false; 74 | } 75 | -------------------------------------------------------------------------------- /conflate/conflate_internal.h: -------------------------------------------------------------------------------- 1 | /* Internal data structures that should be opaque to outside viewers */ 2 | #ifndef CONFLATE_INTERNAL_H 3 | #define CONFLATE_INTERNAL_H 1 4 | 5 | #include 6 | 7 | #ifdef CONFLATE_USE_XMPP 8 | #include 9 | #else 10 | #define xmpp_ctx_t void 11 | #define xmpp_conn_t void 12 | #endif 13 | 14 | struct _conflate_handle { 15 | 16 | xmpp_ctx_t *ctx; 17 | xmpp_conn_t *conn; 18 | 19 | conflate_config_t *conf; 20 | 21 | cb_thread_t thread; 22 | 23 | char *url; /* Current URL for debuggability. */ 24 | }; 25 | 26 | void conflate_init_commands(void); 27 | 28 | #endif /* CONFLATE_INTERNAL_H */ 29 | -------------------------------------------------------------------------------- /conflate/logging.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include 6 | #include "conflate_internal.h" 7 | 8 | static char* lvl_name(enum conflate_log_level lvl) 9 | { 10 | char *rv = NULL; 11 | 12 | switch(lvl) { 13 | case LOG_LVL_FATAL: rv = "FATAL"; break; 14 | case LOG_LVL_ERROR: rv = "ERROR"; break; 15 | case LOG_LVL_WARN: rv = "WARN"; break; 16 | case LOG_LVL_INFO: rv = "INFO"; break; 17 | case LOG_LVL_DEBUG: rv = "DEBUG"; break; 18 | } 19 | 20 | return rv; 21 | } 22 | 23 | void conflate_stderr_logger(void *userdata, enum conflate_log_level lvl, 24 | const char *msg, ...) 25 | { 26 | char fmt[512]; 27 | va_list ap; 28 | 29 | snprintf(fmt, sizeof(fmt), "%s: %s\n", lvl_name(lvl), msg); 30 | va_start(ap, msg); 31 | vfprintf(stderr, fmt, ap); 32 | va_end(ap); 33 | (void)userdata; 34 | } 35 | -------------------------------------------------------------------------------- /conflate/persist.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include "conflate_internal.h" 8 | 9 | kvpair_t* load_kvpairs(conflate_handle_t *handle, const char *filename) 10 | { 11 | (void)handle; 12 | (void)filename; 13 | return NULL; 14 | } 15 | 16 | bool save_kvpairs(conflate_handle_t *handle, kvpair_t* kvpair, 17 | const char *filename) 18 | { 19 | (void)handle; 20 | (void)kvpair; 21 | (void)filename; 22 | return true; 23 | } 24 | 25 | bool conflate_delete_private(conflate_handle_t *handle, 26 | const char *k, const char *filename) 27 | { 28 | (void)handle; 29 | (void)k; 30 | (void)filename; 31 | return true; 32 | } 33 | 34 | bool conflate_save_private(conflate_handle_t *handle, 35 | const char *k, const char *v, const char *filename) 36 | { 37 | (void)handle; 38 | (void)k; 39 | (void)v; 40 | (void)filename; 41 | return true; 42 | } 43 | 44 | char *conflate_get_private(conflate_handle_t *handle, 45 | const char *k, const char *filename) 46 | { 47 | (void)handle; 48 | (void)k; 49 | (void)filename; 50 | return NULL; 51 | } 52 | -------------------------------------------------------------------------------- /conflate/rest.h: -------------------------------------------------------------------------------- 1 | #ifndef REST_H 2 | #define REST_H 3 | 4 | #define RESPONSE_BUFFER_SIZE 4096 5 | #define END_OF_CONFIG "\n\n\n\n" 6 | #define CONFIG_KEY "contents" 7 | #define HTTP_CODE_KEY "http_code" 8 | 9 | void run_rest_conflate(void *arg); 10 | 11 | #endif /* REST_H */ 12 | 13 | -------------------------------------------------------------------------------- /conflate/util.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | 8 | char* safe_strdup(const char* in) { 9 | int len = strlen(in); 10 | char *rv = calloc(len + 1, sizeof(char)); 11 | cb_assert(rv); 12 | memcpy(rv, in, len); 13 | return rv; 14 | } 15 | 16 | void free_string_list(char **vals) 17 | { 18 | int i = 0; 19 | for (i = 0; vals[i]; i++) { 20 | free(vals[i]); 21 | } 22 | free(vals); 23 | } 24 | -------------------------------------------------------------------------------- /conflate/xmpp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include "conflate_internal.h" 8 | 9 | /** \private */ 10 | struct command_def { 11 | char *name; 12 | char *description; 13 | conflate_mgmt_cb_t cb; 14 | struct command_def *next; 15 | }; 16 | 17 | struct command_def *commands = NULL; 18 | 19 | void* run_conflate(void *arg); 20 | 21 | void conflate_init_form(conflate_form_result *r) 22 | { 23 | (void)r; 24 | } 25 | 26 | void conflate_next_fieldset(conflate_form_result *r) { 27 | (void)r; 28 | cb_assert(0); 29 | } 30 | 31 | void conflate_add_field(conflate_form_result *r, const char *k, const char *v) { 32 | (void)r; 33 | (void)k; 34 | (void)v; 35 | cb_assert(0); 36 | } 37 | 38 | void conflate_add_field_multi(conflate_form_result *r, const char *k, 39 | const char **v) { 40 | (void)r; 41 | (void)k; 42 | (void)v; 43 | cb_assert(0); 44 | } 45 | 46 | void* run_conflate(void *arg) { 47 | (void)arg; 48 | cb_assert(0); 49 | return NULL; 50 | } 51 | 52 | /* ------------------------------------------------------------------------ */ 53 | 54 | void conflate_register_mgmt_cb(const char *cmd, const char *desc, 55 | conflate_mgmt_cb_t cb) 56 | { 57 | struct command_def *c = calloc(1, sizeof(struct command_def)); 58 | cb_assert(c); 59 | 60 | c->name = safe_strdup(cmd); 61 | c->description = safe_strdup(desc); 62 | c->cb = cb; 63 | c->next = commands; 64 | 65 | commands = c; 66 | } 67 | -------------------------------------------------------------------------------- /debian/changelog.in: -------------------------------------------------------------------------------- 1 | moxi (@VERSION@-1) unstable; urgency=low 2 | 3 | * Packaged @VERSION@ 4 | 5 | -- Northscale @DATE@ 6 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: moxi 2 | Section: web 3 | Priority: optional 4 | Maintainer: Northscale 5 | Build-Depends: debhelper (>= 5), libevent-dev, check, libsqlite3-dev, libssl-dev, pkg-config, automake, libtool, git-core 6 | Standards-Version: 3.8.1 7 | Homepage: http://labs.northscale.com/moxi 8 | 9 | Package: moxi 10 | Architecture: any 11 | Depends: ${shlibs:Depends}, ${misc:Depends}, lsb-base (>= 3.2) 12 | Description: a high performance, multithreaded memcached proxy 13 | moxi is a high performance memcached proxy with several optimizations 14 | which may be useful when deploying memcached at a large scale or in 15 | cloud compute environments. moxi was produced by NorthScale and is 16 | Open Source under the BSD license. 17 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Moxi is based on code of memcached (http://www.danga.com/memcached/) and is 2 | licensed under same license -- BSD. 3 | 4 | On Debian systems, the complete text of the BSD License can be 5 | found in `/usr/share/common-licenses/BSD'. 6 | -------------------------------------------------------------------------------- /debian/dirs: -------------------------------------------------------------------------------- 1 | usr/bin 2 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | README 2 | AUTHORS 3 | COPYING 4 | doc/CONTRIBUTORS 5 | scripts/examples/ 6 | -------------------------------------------------------------------------------- /debian/moxi.default: -------------------------------------------------------------------------------- 1 | # Defaults for moxi initscript 2 | # sourced by /etc/init.d/moxi 3 | # installed at /etc/default/moxi by the maintainer scripts 4 | 5 | # 6 | # This is a POSIX shell fragment 7 | # 8 | 9 | # uncomment to enable moxi 10 | #RUN="yes" 11 | MAXCONN=1024 12 | PIDFILE=/var/run/moxi/moxi.pid 13 | PROXY_ARG="-z /etc/moxi.conf" 14 | # Additional options that are passed to the Daemon. 15 | DAEMON_OPTS="-u nobody -d -c $MAXCONN $PROXY_ARG -P $PIDFILE" 16 | -------------------------------------------------------------------------------- /debian/moxi.examples: -------------------------------------------------------------------------------- 1 | scripts/examples/* 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | # Sample debian/rules that uses debhelper. 4 | # This file was originally written by Joey Hess and Craig Small. 5 | # As a special exception, when this file is copied by dh-make into a 6 | # dh-make output file, you may use that output file without restriction. 7 | # This special exception was added by Craig Small in version 0.37 of dh-make. 8 | 9 | # Uncomment this to turn on verbose mode. 10 | #export DH_VERBOSE=1 11 | 12 | 13 | 14 | 15 | 16 | configure: configure-stamp 17 | configure-stamp: 18 | dh_testdir 19 | 20 | CONFLATE_DB_PATH=/var/lib/moxi ./configure --prefix=/usr --disable-coverage --disable-debug --disable-shared --without-memcached --with-bundled-libstrophe --with-libconflate=bundled 21 | 22 | touch configure-stamp 23 | 24 | 25 | build: build-stamp 26 | 27 | build-stamp: configure-stamp 28 | dh_testdir 29 | $(MAKE) 30 | 31 | touch $@ 32 | 33 | clean: 34 | dh_testdir 35 | dh_testroot 36 | rm -f build-stamp configure-stamp 37 | 38 | -$(MAKE) distclean 39 | 40 | dh_clean 41 | 42 | install: build 43 | dh_testdir 44 | dh_testroot 45 | -dh_prep 46 | dh_installdirs 47 | 48 | mkdir -p $(CURDIR)/debian/moxi/var/run/moxi 49 | chown nobody:nogroup -R $(CURDIR)/debian/moxi/var/run/moxi 50 | 51 | $(MAKE) DESTDIR=$(CURDIR)/debian/moxi install 52 | 53 | # we don't need headers and static libs from conflate & strophe 54 | rm -rf $(CURDIR)/debian/moxi/usr/lib 55 | rm -rf $(CURDIR)/debian/moxi/usr/include 56 | 57 | mkdir -p $(CURDIR)/debian/moxi/var/lib/moxi 58 | chown nobody:nogroup -R $(CURDIR)/debian/moxi/var/lib/moxi 59 | 60 | # Build architecture-independent files here. 61 | binary-indep: install 62 | # We have nothing to do by default. 63 | 64 | # Build architecture-dependent files here. 65 | binary-arch: install 66 | dh_testdir 67 | dh_testroot 68 | dh_installchangelogs 69 | dh_installdocs 70 | dh_installexamples 71 | # dh_install 72 | # dh_installmenu 73 | # dh_installdebconf 74 | # dh_installlogrotate 75 | # dh_installemacsen 76 | # dh_installpam 77 | # dh_installmime 78 | # dh_python 79 | dh_installinit 80 | # dh_installcron 81 | # dh_installinfo 82 | dh_installman 83 | dh_link 84 | dh_strip 85 | dh_compress 86 | dh_fixperms -Xvar/run/moxi -Xvar/lib/moxi 87 | # dh_perl 88 | # dh_makeshlibs 89 | dh_installdeb 90 | dh_shlibdeps 91 | dh_gencontrol 92 | dh_md5sums 93 | dh_builddeb 94 | 95 | binary: binary-indep binary-arch 96 | .PHONY: build clean binary-indep binary-arch binary install configure 97 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /devtools/clean-whitespace.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | use strict; 3 | use FindBin qw($Bin); 4 | chdir "$Bin/.." or die; 5 | my @files = (glob("*.h"), glob("*.c"), glob("*.ac")); 6 | foreach my $f (@files) { 7 | open(my $fh, $f) or die; 8 | my $before = do { local $/; <$fh>; }; 9 | close ($fh); 10 | my $after = $before; 11 | $after =~ s/\t/ /g; 12 | $after =~ s/ +$//mg; 13 | $after .= "\n" unless $after =~ /\n$/; 14 | next if $after eq $before; 15 | open(my $fh, ">$f") or die; 16 | print $fh $after; 17 | close($fh); 18 | } 19 | -------------------------------------------------------------------------------- /devtools/svn-tarballs.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use FindBin qw($Bin); 5 | 6 | my %branch = ( 7 | '1.2.x' => "http://code.sixapart.com/svn/memcached/trunk/server", 8 | '1.1.x' => "http://code.sixapart.com/svn/memcached/branches/memcached-1.1.x", 9 | ); 10 | 11 | foreach my $b (keys %branch) { 12 | chdir $Bin or die; 13 | my $url = $branch{$b}; 14 | my $out = `svn info $b`; 15 | unless ($out =~ /^URL: (.+)/m && $1 eq $url) { 16 | system("rm -rf $b"); 17 | system("svn", "co", $url, $b) 18 | and die "Failed to checkout $url\n"; 19 | } else { 20 | chdir "$Bin/$b" or die; 21 | system("svn up") and die "Failed to svn up"; 22 | } 23 | 24 | chdir "$Bin/$b" or die; 25 | $out = `svn info .`; 26 | 27 | my ($maxrev) = $out =~ /^Last Changed Rev: (\d+)/m 28 | or die "No max rev?"; 29 | 30 | print "$b = $maxrev\n"; 31 | my $distfile = "memcached-$b-svn$maxrev.tar.gz"; 32 | next if -f $distfile && -s _; 33 | 34 | open(my $fh, "configure.ac") or die "no configure.ac in $b?"; 35 | my $ac = do { local $/; <$fh>; }; 36 | close($fh); 37 | $ac =~ s!AC_INIT\(memcached,.+?\)!AC_INIT(memcached, $b-svn$maxrev, brad\@danga.com)! 38 | or die "Failed to replace"; 39 | open (my $fh, ">configure.ac") or die "failed to write configure.ac writeable: $!"; 40 | print $fh $ac; 41 | close ($fh); 42 | 43 | system("./autogen.sh") and die "Autogen failed. Missing autotools?"; 44 | system("./configure") and die "configure failed"; 45 | system("make dist") and die "make dist failed"; 46 | die "Failed to make dist $distfile." unless -s $distfile; 47 | } 48 | 49 | 50 | -------------------------------------------------------------------------------- /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 | 11 | Major authors: 12 | -------------- 13 | 14 | Brad Fitzpatrick -- maintainer, original implementations 15 | 16 | Anatoly Vorobey -- lots of the modern server code 17 | 18 | Steven Grimm -- iov writing (less CPU), UDP mode, 19 | non-2.0 slab mantissas, multithread, ... 20 | 21 | Other Contributors 22 | ------------------ 23 | 24 | Evan Martin 25 | Nathan Neulinger 26 | Eric Hodel 27 | Michael Johnson 28 | Paul Querna 29 | Jamie McCarthy 30 | Philip Neustrom 31 | Andrew O'Brien 32 | Josh Rotenberg 33 | Robin H. Johnson 34 | Tim Yardley 35 | Paolo Borelli 36 | Eli Bingham 37 | Jean-Francois Bustarret 38 | Paul G 39 | Paul Lindner 40 | Dormando 41 | Dustin Sallings 42 | Chris Goffinet 43 | Tomash Brechko 44 | Brian Aker 45 | Trond Norbye 46 | -------------------------------------------------------------------------------- /doc/Makefile.am: -------------------------------------------------------------------------------- 1 | man_MANS = moxi.1 2 | 3 | EXTRA_DIST = *.txt 4 | 5 | BUILT_SOURCES= 6 | -------------------------------------------------------------------------------- /doc/building-moxi-packages.txt: -------------------------------------------------------------------------------- 1 | For Fedora 2 | ---------- 3 | 4 | First setup your build environment as pointed out in 5 | http://fedoraproject.org/wiki/How_to_create_an_RPM_package 6 | 7 | $ rpmdev-setuptree 8 | 9 | Then 10 | 11 | $ ./autogen.sh && ./configure --with-libconflate=bundled \ 12 | --with-bundled-libstrophe && make fc_rpm 13 | 14 | this will produce source and binary rpms for your architecture. 15 | 16 | For Debian/Ubuntu 17 | ----------------- 18 | 19 | $ ./autogen.sh && ./configure --with-libconflate=bundled \ 20 | --with-bundled-libstrophe && make dist 21 | 22 | Than unpack moxi .tar.gz source archive and inside source directory 23 | run 24 | 25 | $ dpkg-buildpackage 26 | -------------------------------------------------------------------------------- /doc/readme.txt: -------------------------------------------------------------------------------- 1 | To build the documentation you need xml2rfc ( http://xml.resource.org/ ). 2 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /include/libvbucket/visibility.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | /* 3 | * Copyright 2010 NorthScale, Inc. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef LIBVBUCKET_VISIBILITY_H 18 | #define LIBVBUCKET_VISIBILITY_H 1 19 | 20 | #ifdef BUILDING_LIBVBUCKET 21 | 22 | #if defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550) 23 | #define LIBVBUCKET_PUBLIC_API __global 24 | #elif defined __GNUC__ 25 | #define LIBVBUCKET_PUBLIC_API __attribute__ ((visibility("default"))) 26 | #elif defined(_MSC_VER) 27 | #define LIBVBUCKET_PUBLIC_API extern __declspec(dllexport) 28 | #else 29 | /* unknown compiler */ 30 | #define LIBVBUCKET_PUBLIC_API 31 | #endif 32 | 33 | #else 34 | 35 | #if defined(_MSC_VER) 36 | #define LIBVBUCKET_PUBLIC_API extern __declspec(dllimport) 37 | #else 38 | #define LIBVBUCKET_PUBLIC_API 39 | #endif 40 | 41 | #endif 42 | 43 | #endif /* LIBVBUCKET_VISIBILITY_H */ 44 | -------------------------------------------------------------------------------- /libmemcached/.gitignore: -------------------------------------------------------------------------------- 1 | /CMakeFiles/ 2 | /CTestTestfile.cmake 3 | /Makefile 4 | /cmake_install.cmake 5 | /libhashkit.so* 6 | /libmcd.so* 7 | /hashkit.dll* 8 | /hashkit.exp 9 | /hashkit.ilk 10 | /hashkit.lib 11 | /hashkit.pdb 12 | /mcd.dll* 13 | /mcd.exp 14 | /mcd.ilk 15 | /mcd.lib 16 | /mcd.pdb 17 | /libmcd*dylib 18 | /libhashkit*dylib 19 | -------------------------------------------------------------------------------- /libmemcached/AUTHORS: -------------------------------------------------------------------------------- 1 | Brian Aker, brian@tangent.org -- Client Library, Tools 2 | Mark Atwood, -- Tools, Docs 3 | Patrick Galbraith, -- C++ Interface 4 | Padraig O'Sullivan, -- C++ Interface (current one) 5 | Tim Bunce, -- Docs 6 | Trond Norbye, trond.norbye@gmail.com -- Binary protocol, Misc 7 | Yin Chen, -- Ketama Work 8 | Toru Maesaka, dev@torum.net -- Stats analysis 9 | Eric Lambert, -- UDP work 10 | Monty Taylor, -- Build Releated (Pandora) 11 | Mingqiang Zhuang, Schooner Information Technology, Inc. -- Rewrite of memslap 12 | -------------------------------------------------------------------------------- /libmemcached/COPYING: -------------------------------------------------------------------------------- 1 | Software License Agreement (BSD License) 2 | 3 | Copyright (c) 2007, TangentOrg (Brian Aker) 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are 8 | met: 9 | 10 | * Redistributions of source code must retain the above copyright 11 | notice, this list of conditions and the following disclaimer. 12 | 13 | * Redistributions in binary form must reproduce the above 14 | copyright notice, this list of conditions and the following disclaimer 15 | in the documentation and/or other materials provided with the 16 | distribution. 17 | 18 | * Neither the name of TangentOrg nor the names of its 19 | contributors may be used to endorse or promote products derived from 20 | this software without specific prior written permission. 21 | 22 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 | -------------------------------------------------------------------------------- /libmemcached/NEWS: -------------------------------------------------------------------------------- 1 | See Changelog 2 | -------------------------------------------------------------------------------- /libmemcached/README: -------------------------------------------------------------------------------- 1 | Hi! 2 | 3 | So what is this? It is a library in C for connecting to memcached servers 4 | (http://danga.com/memcached/). It is also a collection of utilities designed 5 | to work with memcached. 6 | 7 | memcat - Copy the value of a key to standard output 8 | memflush - Flush the contents of your servers. 9 | memrm - Remove a key(s) from the server. 10 | memstat - Dump the stats of your servers to standard output 11 | memslap - Load generation utility (benchmark!) 12 | 13 | The utilities are beta quality at this point. The library is in production 14 | in many locations (upwards to 1000+ nodes). 15 | 16 | Want to contribute? If you write more then three good patches, then I will 17 | just ask you to commit directly to the tree. I am happy to have additional 18 | people work on this project. Please checkout README.FIRST. 19 | 20 | You will need a C99 compiler in order to compile this library. Currently we 21 | actively support Linux, MacOSX, FreeBSD, and Solaris. A Windows port is 22 | currently not supported, but one is listed on the homepage that is supported 23 | by someone in the community. 24 | 25 | If you are looking for answers to your questions please check out the 26 | mailing list at: 27 | http://lists.tangent.org/ 28 | 29 | Subscription information for the libmemcached mailing list can be found there. 30 | 31 | Cheers, 32 | -Brian Aker 33 | Seattle, WA. 34 | -------------------------------------------------------------------------------- /libmemcached/README.FIRST: -------------------------------------------------------------------------------- 1 | Hi! 2 | 3 | If you are getting this code from http://launchpad.net/libmemcached then 4 | continue reading. Otherwise these directions are not for you (well maybe...). 5 | 6 | To obtain code from http://bazaar.launchpad.net/libmemcached you will need to 7 | issue the following command: 8 | 9 | bzr branch lp:libmemcached 10 | 11 | Once the tree is cloned you will need to build the "configure" script. You 12 | can do this by running the script: 13 | 14 | ./config/autorun.sh 15 | 16 | It will set up all of the files you need to build libmemcached. At that 17 | point it is just the typical "./configure; make; make test; make install" 18 | 19 | For a tarball release do a "make dist" and for an RPM type "make rpm". 20 | 21 | For patches, we prefer you push a branch to launchpad and then submit that 22 | branch to be merged. For more information, see: 23 | 24 | https://help.launchpad.net/Code/UploadingABranch 25 | https://help.launchpad.net/Code/Review 26 | 27 | Thanks and keep hacking! 28 | 29 | Cheers, 30 | -Brian 31 | Seattle, WA. 32 | -------------------------------------------------------------------------------- /libmemcached/README.win32: -------------------------------------------------------------------------------- 1 | Hi, 2 | 3 | So you want to know how to build libmemcached on Windows? In order to 4 | have a single build environment you need to install mingw to get a 5 | "unix environment" to run the configure script. 6 | 7 | An easy way to get started is to install the msysgit fullinstall 8 | package from: http://code.google.com/p/msysgit/downloads/list 9 | 10 | msysgit does not contain the "autotools" needed to generate a 11 | configure script, so you need to generate that on another box (this 12 | should not be a problem if you're trying to build from a tar archive). 13 | 14 | msysgit does not contain the tools to build the documentation, so you 15 | need to add --without-docs to configure. 16 | 17 | I'm normally building libmemcached with: 18 | 19 | Ex: 20 | $ ./configure --without-docs --with-memcached=../memcached/memcached.exe 21 | $ make all install 22 | 23 | Happy hacking, 24 | 25 | Trond Norbye 26 | -------------------------------------------------------------------------------- /libmemcached/THANKS: -------------------------------------------------------------------------------- 1 | (This is not complete, please send email if I have missed someone.) 2 | Eirik A. Nygaard - IO Patch 3 | Cal Heldenbrand - Awesome feedback on performance 4 | Dustin Sallings - Insight into protocol 5 | Tobias Luetke - Performance Feedback 6 | Andre Cruz - Help with getting the CRC Hash function to match other connectors 7 | Brian Pontz - Hsieh hash 8 | Tim Bunce - Perl Driver work and feedback on API 9 | Kevin Dalley - Bug Fixes 10 | Patrick Galbraith - work on C++ interface 11 | Ross McFarland - Idea for sorting servers. 12 | Marcelo Fernandez - TCP/IP timeout pieces 13 | Yin Chen - Ketama support/weighted support 14 | Monty Taylor - Debian Packages, Cleanup work for configure 15 | -------------------------------------------------------------------------------- /libmemcached/TODO: -------------------------------------------------------------------------------- 1 | - Write a shell application (?) 2 | - Fix version in command line tools 3 | - Write (more) test cases for all command line tools (!!!) 4 | - Write some sort of "default" options bit for tools 5 | - More examples using libraries 6 | - Doxygen? 7 | - implement more connection/hash algo 8 | - implement compression 9 | - Revisit get() code (look for performance enhancements) 10 | - Add support for managing servers for clusters. 11 | - Build embedded version 12 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/algorithm.c: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #include "common.h" 10 | 11 | uint32_t libhashkit_one_at_a_time(const char *key, size_t key_length) 12 | { 13 | return hashkit_one_at_a_time(key, key_length, NULL); 14 | } 15 | 16 | uint32_t libhashkit_fnv1_64(const char *key, size_t key_length) 17 | { 18 | return hashkit_fnv1_64(key, key_length, NULL); 19 | } 20 | 21 | uint32_t libhashkit_fnv1a_64(const char *key, size_t key_length) 22 | { 23 | return hashkit_fnv1a_64(key, key_length, NULL); 24 | } 25 | 26 | uint32_t libhashkit_fnv1_32(const char *key, size_t key_length) 27 | { 28 | return hashkit_fnv1_32(key, key_length, NULL); 29 | } 30 | 31 | uint32_t libhashkit_fnv1a_32(const char *key, size_t key_length) 32 | { 33 | return hashkit_fnv1a_32(key, key_length, NULL); 34 | } 35 | 36 | uint32_t libhashkit_crc32(const char *key, size_t key_length) 37 | { 38 | return hashkit_crc32(key, key_length, NULL); 39 | } 40 | 41 | #ifdef HAVE_HSIEH_HASH 42 | uint32_t libhashkit_hsieh(const char *key, size_t key_length) 43 | { 44 | return hashkit_hsieh(key, key_length, NULL); 45 | } 46 | #endif 47 | 48 | #ifdef HAVE_MURMUR_HASH 49 | uint32_t libhashkit_murmur(const char *key, size_t key_length) 50 | { 51 | return hashkit_murmur(key, key_length, NULL); 52 | } 53 | #endif 54 | 55 | uint32_t libhashkit_jenkins(const char *key, size_t key_length) 56 | { 57 | return hashkit_jenkins(key, key_length, NULL); 58 | } 59 | 60 | uint32_t libhashkit_md5(const char *key, size_t key_length) 61 | { 62 | return hashkit_md5(key, key_length, NULL); 63 | } 64 | 65 | void libhashkit_md5_signature(const unsigned char *key, size_t length, unsigned char *result) 66 | { 67 | md5_signature(key, (uint32_t)length, result); 68 | } 69 | 70 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/algorithm.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | /** 10 | * @file 11 | * @brief HashKit Header 12 | */ 13 | 14 | #ifndef HASHKIT_ALGORITHM_H 15 | #define HASHKIT_ALGORITHM_H 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | HASHKIT_API 22 | uint32_t libhashkit_one_at_a_time(const char *key, size_t key_length); 23 | 24 | HASHKIT_API 25 | uint32_t libhashkit_fnv1_64(const char *key, size_t key_length); 26 | 27 | HASHKIT_API 28 | uint32_t libhashkit_fnv1a_64(const char *key, size_t key_length); 29 | 30 | HASHKIT_API 31 | uint32_t libhashkit_fnv1_32(const char *key, size_t key_length); 32 | 33 | HASHKIT_API 34 | uint32_t libhashkit_fnv1a_32(const char *key, size_t key_length); 35 | 36 | HASHKIT_API 37 | uint32_t libhashkit_crc32(const char *key, size_t key_length); 38 | 39 | HASHKIT_API 40 | uint32_t libhashkit_jenkins(const char *key, size_t key_length); 41 | 42 | HASHKIT_API 43 | uint32_t libhashkit_md5(const char *key, size_t key_length); 44 | 45 | HASHKIT_LOCAL 46 | uint32_t hashkit_one_at_a_time(const char *key, size_t key_length, void *context); 47 | 48 | HASHKIT_LOCAL 49 | uint32_t hashkit_fnv1_64(const char *key, size_t key_length, void *context); 50 | 51 | HASHKIT_LOCAL 52 | uint32_t hashkit_fnv1a_64(const char *key, size_t key_length, void *context); 53 | 54 | HASHKIT_LOCAL 55 | uint32_t hashkit_fnv1_32(const char *key, size_t key_length, void *context); 56 | 57 | HASHKIT_LOCAL 58 | uint32_t hashkit_fnv1a_32(const char *key, size_t key_length, void *context); 59 | 60 | HASHKIT_LOCAL 61 | uint32_t hashkit_crc32(const char *key, size_t key_length, void *context); 62 | 63 | HASHKIT_LOCAL 64 | uint32_t hashkit_jenkins(const char *key, size_t key_length, void *context); 65 | 66 | HASHKIT_LOCAL 67 | uint32_t hashkit_md5(const char *key, size_t key_length, void *context); 68 | 69 | HASHKIT_API 70 | void libhashkit_md5_signature(const unsigned char *key, size_t length, unsigned char *result); 71 | 72 | #ifdef __cplusplus 73 | } 74 | #endif 75 | 76 | #endif /* HASHKIT_ALGORITHM_H */ 77 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/behavior.c: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #include "common.h" 10 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/behavior.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | /** 10 | * @file 11 | * @brief HashKit Header 12 | */ 13 | 14 | #ifndef HASHKIT_BEHAVIOR_H 15 | #define HASHKIT_BEHAVIOR_H 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif /* HASHKIT_BEHAVIOR_H */ 27 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/common.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #ifndef HASHKIT_COMMON_H 10 | #define HASHKIT_COMMON_H 11 | 12 | #include "libmemcached_config.h" 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "hashkit.h" 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | HASHKIT_LOCAL 27 | void md5_signature(const unsigned char *key, unsigned int length, unsigned char *result); 28 | 29 | HASHKIT_LOCAL 30 | int update_continuum(hashkit_st *hashkit); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | 36 | #endif /* HASHKIT_COMMON_H */ 37 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/configure.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009-2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | #ifndef LIBHASHKIT_CONFIGURE_H 9 | #define LIBHASHKIT_CONFIGURE_H 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif /* LIBHASHKIT_CONFIGURE_H */ 20 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/configure.h.in: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009-2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | #ifndef LIBHASHKIT_CONFIGURE_H 9 | #define LIBHASHKIT_CONFIGURE_H 10 | 11 | #ifdef __cplusplus 12 | extern "C" { 13 | #endif 14 | 15 | #ifdef __cplusplus 16 | } 17 | #endif 18 | 19 | #endif /* LIBHASHKIT_CONFIGURE_H */ 20 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/digest.c: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #include "common.h" 10 | 11 | uint32_t hashkit_digest(const hashkit_st *self, const char *key, size_t key_length) 12 | { 13 | return self->base_hash.function(key, key_length, self->base_hash.context); 14 | } 15 | 16 | uint32_t libhashkit_digest(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm) 17 | { 18 | switch (hash_algorithm) 19 | { 20 | case HASHKIT_HASH_DEFAULT: 21 | return libhashkit_one_at_a_time(key, key_length); 22 | case HASHKIT_HASH_MD5: 23 | return libhashkit_md5(key, key_length); 24 | case HASHKIT_HASH_CRC: 25 | return libhashkit_crc32(key, key_length); 26 | case HASHKIT_HASH_FNV1_64: 27 | return libhashkit_fnv1_64(key, key_length); 28 | case HASHKIT_HASH_FNV1A_64: 29 | return libhashkit_fnv1a_64(key, key_length); 30 | case HASHKIT_HASH_FNV1_32: 31 | return libhashkit_fnv1_32(key, key_length); 32 | case HASHKIT_HASH_FNV1A_32: 33 | return libhashkit_fnv1a_32(key, key_length); 34 | case HASHKIT_HASH_HSIEH: 35 | #ifdef HAVE_HSIEH_HASH 36 | return libhashkit_hsieh(key, key_length); 37 | #else 38 | return 1; 39 | #endif 40 | case HASHKIT_HASH_MURMUR: 41 | #ifdef HAVE_MURMUR_HASH 42 | return libhashkit_murmur(key, key_length); 43 | #else 44 | return 1; 45 | #endif 46 | case HASHKIT_HASH_JENKINS: 47 | return libhashkit_jenkins(key, key_length); 48 | case HASHKIT_HASH_CUSTOM: 49 | case HASHKIT_HASH_MAX: 50 | default: 51 | #ifdef HAVE_DEBUG 52 | fprintf(stderr, "hashkit_hash_t was extended but libhashkit_generate_value was not updated\n"); 53 | fflush(stderr); 54 | cb_assert(0); 55 | #endif 56 | break; 57 | } 58 | 59 | return 1; 60 | } 61 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/digest.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #ifndef HASHKIT_DIGEST_H 10 | #define HASHKIT_DIGEST_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | HASHKIT_API 17 | uint32_t hashkit_digest(const hashkit_st *self, const char *key, size_t key_length); 18 | 19 | /** 20 | This is a utilitly function provided so that you can directly access hashes with a hashkit_st. 21 | */ 22 | 23 | HASHKIT_API 24 | uint32_t libhashkit_digest(const char *key, size_t key_length, hashkit_hash_algorithm_t hash_algorithm); 25 | 26 | #ifdef __cplusplus 27 | } 28 | #endif 29 | 30 | #endif /* HASHKIT_DIGEST_H */ 31 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/fnv.c: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #include "common.h" 10 | 11 | /* FNV hash'es lifted from Dustin Sallings work */ 12 | static uint64_t FNV_64_INIT= UINT64_C(0xcbf29ce484222325); 13 | static uint64_t FNV_64_PRIME= UINT64_C(0x100000001b3); 14 | static uint32_t FNV_32_INIT= 2166136261UL; 15 | static uint32_t FNV_32_PRIME= 16777619; 16 | 17 | uint32_t hashkit_fnv1_64(const char *key, size_t key_length, void *context) 18 | { 19 | /* Thanks to pierre@demartines.com for the pointer */ 20 | uint64_t hash= FNV_64_INIT; 21 | size_t x; 22 | (void)context; 23 | 24 | for (x= 0; x < key_length; x++) 25 | { 26 | hash *= FNV_64_PRIME; 27 | hash ^= (uint64_t)key[x]; 28 | } 29 | 30 | return (uint32_t)hash; 31 | } 32 | 33 | uint32_t hashkit_fnv1a_64(const char *key, size_t key_length, void *context) 34 | { 35 | uint32_t hash= (uint32_t) FNV_64_INIT; 36 | size_t x; 37 | (void)context; 38 | 39 | for (x= 0; x < key_length; x++) 40 | { 41 | uint32_t val= (uint32_t)key[x]; 42 | hash ^= val; 43 | hash *= (uint32_t) FNV_64_PRIME; 44 | } 45 | 46 | return hash; 47 | } 48 | 49 | uint32_t hashkit_fnv1_32(const char *key, size_t key_length, void *context) 50 | { 51 | uint32_t hash= FNV_32_INIT; 52 | size_t x; 53 | (void)context; 54 | 55 | for (x= 0; x < key_length; x++) 56 | { 57 | uint32_t val= (uint32_t)key[x]; 58 | hash *= FNV_32_PRIME; 59 | hash ^= val; 60 | } 61 | 62 | return hash; 63 | } 64 | 65 | uint32_t hashkit_fnv1a_32(const char *key, size_t key_length, void *context) 66 | { 67 | uint32_t hash= FNV_32_INIT; 68 | size_t x; 69 | (void)context; 70 | 71 | for (x= 0; x < key_length; x++) 72 | { 73 | uint32_t val= (uint32_t)key[x]; 74 | hash ^= val; 75 | hash *= FNV_32_PRIME; 76 | } 77 | 78 | return hash; 79 | } 80 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/function.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #ifndef HASHKIT_FUNCTION_H 10 | #define HASHKIT_FUNCTION_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | /** 17 | This sets/gets the default function we will be using. 18 | */ 19 | HASHKIT_API 20 | hashkit_return_t hashkit_set_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm); 21 | 22 | HASHKIT_API 23 | hashkit_return_t hashkit_set_custom_function(hashkit_st *hash, hashkit_hash_fn function, void *context); 24 | 25 | HASHKIT_API 26 | hashkit_hash_algorithm_t hashkit_get_function(const hashkit_st *hash); 27 | 28 | /** 29 | This sets/gets the function we use for distribution. 30 | */ 31 | HASHKIT_API 32 | hashkit_return_t hashkit_set_distribution_function(hashkit_st *hash, hashkit_hash_algorithm_t hash_algorithm); 33 | 34 | HASHKIT_API 35 | hashkit_return_t hashkit_set_custom_distribution_function(hashkit_st *self, hashkit_hash_fn function, void *context); 36 | 37 | HASHKIT_API 38 | hashkit_hash_algorithm_t hashkit_get_distribution_function(const hashkit_st *self); 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif 43 | 44 | #endif /* HASHKIT_FUNCTION_H */ 45 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/hashkit.c: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #include "common.h" 10 | #include 11 | 12 | static bool _hashkit_init(hashkit_st *self) 13 | { 14 | memset(self, 0, sizeof(*self)); 15 | self->base_hash.function = hashkit_one_at_a_time; 16 | return true; 17 | } 18 | 19 | static hashkit_st *_hashkit_create(hashkit_st *self) 20 | { 21 | if (self == NULL) 22 | { 23 | self= (hashkit_st *)malloc(sizeof(hashkit_st)); 24 | if (self == NULL) 25 | { 26 | return NULL; 27 | } 28 | 29 | self->options.is_allocated= true; 30 | } 31 | else 32 | { 33 | self->options.is_allocated= false; 34 | } 35 | 36 | return self; 37 | } 38 | 39 | hashkit_st *hashkit_create(hashkit_st *self) 40 | { 41 | self= _hashkit_create(self); 42 | if (! self) 43 | return self; 44 | 45 | if (! _hashkit_init(self)) 46 | { 47 | hashkit_free(self); 48 | } 49 | 50 | return self; 51 | } 52 | 53 | 54 | void hashkit_free(hashkit_st *self) 55 | { 56 | if (hashkit_is_allocated(self)) 57 | { 58 | free(self); 59 | } 60 | } 61 | 62 | hashkit_st *hashkit_clone(hashkit_st *destination, const hashkit_st *source) 63 | { 64 | if (source == NULL) 65 | { 66 | return hashkit_create(destination); 67 | } 68 | 69 | /* new_clone will be a pointer to destination */ 70 | destination= _hashkit_create(destination); 71 | 72 | /* Should only happen on allocation failure. */ 73 | if (destination == NULL) 74 | { 75 | return NULL; 76 | } 77 | 78 | destination->base_hash= source->base_hash; 79 | destination->distribution_hash= source->distribution_hash; 80 | destination->flags= source->flags; 81 | 82 | return destination; 83 | } 84 | 85 | bool hashkit_compare(const hashkit_st *first, const hashkit_st *second) 86 | { 87 | if (first->base_hash.function == second->base_hash.function && 88 | first->base_hash.context == second->base_hash.context && 89 | first->distribution_hash.function == second->distribution_hash.function && 90 | first->distribution_hash.context == second->distribution_hash.context && 91 | first->flags.is_base_same_distributed == second->flags.is_base_same_distributed) 92 | { 93 | return true; 94 | } 95 | 96 | return false; 97 | } 98 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/one_at_a_time.c: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | /* 10 | This has is Jenkin's "One at A time Hash". 11 | http://en.wikipedia.org/wiki/Jenkins_hash_function 12 | */ 13 | 14 | #include "common.h" 15 | 16 | uint32_t hashkit_one_at_a_time(const char *key, size_t key_length, void *context) 17 | { 18 | const char *ptr= key; 19 | uint32_t value= 0; 20 | (void)context; 21 | 22 | while (key_length--) 23 | { 24 | uint32_t val= (uint32_t) *ptr++; 25 | value += val; 26 | value += (value << 10); 27 | value ^= (value >> 6); 28 | } 29 | value += (value << 3); 30 | value ^= (value >> 11); 31 | value += (value << 15); 32 | 33 | return value; 34 | } 35 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/strerror.c: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #include "common.h" 10 | 11 | const char *hashkit_strerror(hashkit_st *ptr, hashkit_return_t rc) 12 | { 13 | (void)ptr; 14 | switch (rc) 15 | { 16 | case HASHKIT_SUCCESS: 17 | return "SUCCESS"; 18 | case HASHKIT_FAILURE: 19 | return "FAILURE"; 20 | case HASHKIT_MEMORY_ALLOCATION_FAILURE: 21 | return "MEMORY ALLOCATION FAILURE"; 22 | case HASHKIT_MAXIMUM_RETURN: 23 | return "Gibberish returned!"; 24 | default: 25 | return "Gibberish returned!"; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/strerror.h: -------------------------------------------------------------------------------- 1 | /* HashKit 2 | * Copyright (C) 2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | */ 8 | 9 | #ifndef HASHKIT_STRERROR_H 10 | #define HASHKIT_STRERROR_H 11 | 12 | #ifdef __cplusplus 13 | extern "C" { 14 | #endif 15 | 16 | HASHKIT_API 17 | const char *hashkit_strerror(hashkit_st *ptr, hashkit_return_t rc); 18 | 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | 23 | #endif /* HASHKIT_STRERROR_H */ 24 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/types.h: -------------------------------------------------------------------------------- 1 | 2 | /* HashKit 3 | * Copyright (C) 2009 Brian Aker 4 | * All rights reserved. 5 | * 6 | * Use and distribution licensed under the BSD license. See 7 | * the COPYING file in the parent directory for full text. 8 | */ 9 | 10 | #ifndef HASHKIT_TYPES_H 11 | #define HASHKIT_TYPES_H 12 | 13 | #ifdef __cplusplus 14 | 15 | extern "C" { 16 | #endif 17 | 18 | typedef enum { 19 | HASHKIT_SUCCESS, 20 | HASHKIT_FAILURE, 21 | HASHKIT_MEMORY_ALLOCATION_FAILURE, 22 | HASHKIT_MAXIMUM_RETURN /* Always add new error code before */ 23 | } hashkit_return_t; 24 | 25 | typedef enum { 26 | HASHKIT_HASH_DEFAULT= 0, /* hashkit_one_at_a_time() */ 27 | HASHKIT_HASH_MD5, 28 | HASHKIT_HASH_CRC, 29 | HASHKIT_HASH_FNV1_64, 30 | HASHKIT_HASH_FNV1A_64, 31 | HASHKIT_HASH_FNV1_32, 32 | HASHKIT_HASH_FNV1A_32, 33 | HASHKIT_HASH_HSIEH, 34 | HASHKIT_HASH_MURMUR, 35 | HASHKIT_HASH_JENKINS, 36 | HASHKIT_HASH_CUSTOM, 37 | HASHKIT_HASH_MAX 38 | } hashkit_hash_algorithm_t; 39 | 40 | /** 41 | * Hash distributions that are available to use. 42 | */ 43 | typedef enum 44 | { 45 | HASHKIT_DISTRIBUTION_MODULA, 46 | HASHKIT_DISTRIBUTION_RANDOM, 47 | HASHKIT_DISTRIBUTION_KETAMA, 48 | HASHKIT_DISTRIBUTION_MAX /* Always add new values before this. */ 49 | } hashkit_distribution_t; 50 | 51 | 52 | typedef struct hashkit_st hashkit_st; 53 | 54 | typedef uint32_t (*hashkit_hash_fn)(const char *key, size_t key_length, void *context); 55 | 56 | #ifdef __cplusplus 57 | } 58 | #endif 59 | 60 | #endif /* HASHKIT_TYPES_H */ 61 | -------------------------------------------------------------------------------- /libmemcached/libhashkit/visibility.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Summary: interface for HashKit functions 3 | * Description: visibitliy macros for HashKit library 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in this directory for full text. 7 | * 8 | * Author: Monty Taylor 9 | */ 10 | 11 | /** 12 | * @file 13 | * @brief Visibility control macros 14 | */ 15 | 16 | #ifndef HASHKIT_VISIBILITY_H 17 | #define HASHKIT_VISIBILITY_H 18 | 19 | /** 20 | * 21 | * HASHKIT_API is used for the public API symbols. It either DLL imports or 22 | * DLL exports (or does nothing for static build). 23 | * 24 | * HASHKIT_LOCAL is used for non-api symbols. 25 | */ 26 | 27 | #if defined(BUILDING_HASHKIT) 28 | # if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY 29 | # define HASHKIT_API __attribute__ ((visibility("default"))) 30 | # define HASHKIT_LOCAL __attribute__ ((visibility("hidden"))) 31 | # elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550) 32 | # define HASHKIT_API __global 33 | # define HASHKIT_LOCAL __hidden 34 | # elif defined(_MSC_VER) 35 | # define HASHKIT_API extern __declspec(dllexport) 36 | # define HASHKIT_LOCAL 37 | # else 38 | # define HASHKIT_API 39 | # define HASHKIT_LOCAL 40 | # endif /* defined(HAVE_VISIBILITY) */ 41 | #else /* defined(BUILDING_HASHKIT) */ 42 | # if defined(_MSC_VER) 43 | # define HASHKIT_API extern __declspec(dllimport) 44 | # define HASHKIT_LOCAL 45 | # else 46 | # define HASHKIT_API 47 | # define HASHKIT_LOCAL 48 | # endif /* defined(_MSC_VER) */ 49 | #endif /* defined(BUILDING_HASHKIT) */ 50 | 51 | #endif /* HASHKIT_VISIBILITY_H */ 52 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/allocators.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: work with user defined memory allocators 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_ALLOCATORS_H__ 13 | #define __LIBMEMCACHED_ALLOCATORS_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_API 20 | memcached_return_t memcached_set_memory_allocators(memcached_st *ptr, 21 | memcached_malloc_fn mem_malloc, 22 | memcached_free_fn mem_free, 23 | memcached_realloc_fn mem_realloc, 24 | memcached_calloc_fn mem_calloc, 25 | void *context); 26 | 27 | LIBMEMCACHED_API 28 | void memcached_get_memory_allocators(const memcached_st *ptr, 29 | memcached_malloc_fn *mem_malloc, 30 | memcached_free_fn *mem_free, 31 | memcached_realloc_fn *mem_realloc, 32 | memcached_calloc_fn *mem_calloc); 33 | 34 | LIBMEMCACHED_API 35 | void *memcached_get_memory_allocators_context(const memcached_st *ptr); 36 | 37 | LIBMEMCACHED_LOCAL 38 | void _libmemcached_free(const memcached_st *ptr, void *mem, void *context); 39 | 40 | LIBMEMCACHED_LOCAL 41 | void *_libmemcached_malloc(const memcached_st *ptr, const size_t size, void *context); 42 | 43 | LIBMEMCACHED_LOCAL 44 | void *_libmemcached_realloc(const memcached_st *ptr, void *mem, const size_t size, void *context); 45 | 46 | LIBMEMCACHED_LOCAL 47 | void *_libmemcached_calloc(const memcached_st *ptr, size_t nelem, size_t size, void *context); 48 | 49 | LIBMEMCACHED_LOCAL 50 | struct _allocators_st memcached_allocators_return_default(void); 51 | 52 | #ifdef __cplusplus 53 | } 54 | #endif 55 | 56 | #endif /* __LIBMEMCACHED_ALLOCATORS_H__ */ 57 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/analyze.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Generate a memcached_analysis_st 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_ANALYZE_H__ 13 | #define __LIBMEMCACHED_ANALYZE_H__ 14 | 15 | struct memcached_analysis_st { 16 | memcached_st *root; 17 | uint32_t average_item_size; 18 | uint32_t longest_uptime; 19 | uint32_t least_free_server; 20 | uint32_t most_consumed_server; 21 | uint32_t oldest_server; 22 | double pool_hit_ratio; 23 | uint64_t most_used_bytes; 24 | uint64_t least_remaining_bytes; 25 | }; 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | LIBMEMCACHED_API 32 | memcached_analysis_st *memcached_analyze(memcached_st *memc, 33 | memcached_stat_st *memc_stat, 34 | memcached_return_t *error); 35 | 36 | LIBMEMCACHED_API 37 | void memcached_analyze_free(memcached_analysis_st *); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif /* __LIBMEMCACHED_ANALYZE_H__ */ 44 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/behavior.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Change the behavior of the memcached connection. 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_BEHAVIOR_H__ 13 | #define __LIBMEMCACHED_BEHAVIOR_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_API 20 | memcached_return_t memcached_behavior_set(memcached_st *ptr, const memcached_behavior_t flag, uint64_t data); 21 | 22 | LIBMEMCACHED_API 23 | uint64_t memcached_behavior_get(memcached_st *ptr, const memcached_behavior_t flag); 24 | 25 | LIBMEMCACHED_API 26 | memcached_return_t memcached_behavior_set_distribution(memcached_st *ptr, memcached_server_distribution_t type); 27 | 28 | LIBMEMCACHED_API 29 | memcached_server_distribution_t memcached_behavior_get_distribution(memcached_st *ptr); 30 | 31 | LIBMEMCACHED_API 32 | memcached_return_t memcached_behavior_set_key_hash(memcached_st *ptr, memcached_hash_t type); 33 | 34 | LIBMEMCACHED_API 35 | memcached_hash_t memcached_behavior_get_key_hash(memcached_st *ptr); 36 | 37 | LIBMEMCACHED_API 38 | memcached_return_t memcached_behavior_set_distribution_hash(memcached_st *ptr, memcached_hash_t type); 39 | 40 | LIBMEMCACHED_API 41 | memcached_hash_t memcached_behavior_get_distribution_hash(memcached_st *ptr); 42 | 43 | LIBMEMCACHED_LOCAL 44 | bool _is_auto_eject_host(const memcached_st *ptr); 45 | 46 | 47 | #ifdef __cplusplus 48 | } 49 | #endif 50 | 51 | #endif /* __LIBMEMCACHED_BEHAVIOR_H__ */ 52 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/byteorder.c: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: 9 | * 10 | */ 11 | 12 | #include "byteorder.h" 13 | 14 | /* Byte swap a 64-bit number. */ 15 | #ifndef swap64 16 | static uint64_t swap64(uint64_t in) 17 | { 18 | #ifndef WORDS_BIGENDIAN 19 | /* Little endian, flip the bytes around until someone makes a faster/better 20 | * way to do this. */ 21 | uint64_t rv= 0; 22 | uint8_t x; 23 | for (x= 0; x < 8; x++) 24 | { 25 | rv= (rv << 8) | (in & 0xff); 26 | in >>= 8; 27 | } 28 | return rv; 29 | #else 30 | /* big-endian machines don't need byte swapping */ 31 | return in; 32 | #endif /* WORDS_BIGENDIAN */ 33 | } 34 | #endif 35 | 36 | uint64_t memcached_ntohll(uint64_t value) 37 | { 38 | return swap64(value); 39 | } 40 | 41 | uint64_t memcached_htonll(uint64_t value) 42 | { 43 | return swap64(value); 44 | } 45 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/byteorder.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_BYTEORDER_H__ 13 | #define __LIBMEMCACHED_BYTEORDER_H__ 14 | 15 | #include "libmemcached_config.h" 16 | 17 | #if HAVE_SYS_TYPES_H 18 | #include 19 | #endif 20 | 21 | 22 | /* Define this here, which will turn on the visibilty controls while we're 23 | * building libmemcached. 24 | */ 25 | #define BUILDING_LIBMEMCACHED 1 26 | 27 | #include "libmemcached/memcached.h" 28 | 29 | #ifndef HAVE_HTONLL 30 | #define ntohll(a) memcached_ntohll(a) 31 | #define htonll(a) memcached_htonll(a) 32 | #endif 33 | 34 | LIBMEMCACHED_LOCAL 35 | uint64_t memcached_ntohll(uint64_t); 36 | LIBMEMCACHED_LOCAL 37 | uint64_t memcached_htonll(uint64_t); 38 | 39 | #ifdef linux 40 | /* /usr/include/netinet/in.h defines macros from ntohs() to _bswap_nn to 41 | * optimize the conversion functions, but the prototypes generate warnings 42 | * from gcc. The conversion methods isn't the bottleneck for my app, so 43 | * just remove the warnings by undef'ing the optimization .. 44 | */ 45 | #undef ntohs 46 | #undef ntohl 47 | #undef htons 48 | #undef htonl 49 | #endif 50 | 51 | #endif /*__LIBMEMCACHED_BYTEORDER_H__ */ 52 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/callback.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Change any of the possible callbacks. 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_CALLBACK_H__ 13 | #define __LIBMEMCACHED_CALLBACK_H__ 14 | 15 | struct memcached_callback_st { 16 | memcached_execute_fn *callback; 17 | void *context; 18 | uint32_t number_of_callback; 19 | }; 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | LIBMEMCACHED_API 26 | memcached_return_t memcached_callback_set(memcached_st *ptr, 27 | const memcached_callback_t flag, 28 | void *data); 29 | LIBMEMCACHED_API 30 | void *memcached_callback_get(memcached_st *ptr, 31 | const memcached_callback_t flag, 32 | memcached_return_t *error); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif /* __LIBMEMCACHED_CALLBACK_H__ */ 39 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/configure.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker, Trond Norbye 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Change the behavior of the memcached connection. 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_CONFIGURE_H 13 | #define __LIBMEMCACHED_CONFIGURE_H 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | 20 | 21 | 22 | #define LIBMEMCACHED_VERSION_STRING "0.47" 23 | #define LIBMEMCACHED_VERSION_HEX 0x00047000 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif /* __LIBMEMCACHED_CONFIGURE_H */ 30 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/configure.h.in: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker, Trond Norbye 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Change the behavior of the memcached connection. 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_CONFIGURE_H 13 | #define __LIBMEMCACHED_CONFIGURE_H 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | #define LIBMEMCACHED_VERSION_STRING "@VERSION@" 20 | #define LIBMEMCACHED_VERSION_HEX @PANDORA_HEX_VERSION@ 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif /* __LIBMEMCACHED_CONFIGURE_H */ 27 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/delete.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Delete a key from the server. 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_DELETE_H__ 13 | #define __LIBMEMCACHED_DELETE_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_API 20 | memcached_return_t memcached_delete(memcached_st *ptr, const char *key, size_t key_length, 21 | time_t expiration); 22 | 23 | LIBMEMCACHED_API 24 | memcached_return_t memcached_delete_by_key(memcached_st *ptr, 25 | const char *master_key, size_t master_key_length, 26 | const char *key, size_t key_length, 27 | time_t expiration); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif /* __LIBMEMCACHED_DELETE_H__ */ 34 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/do.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Internal functions used by the library. Not for public use! 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_DO_H__ 13 | #define __LIBMEMCACHED_DO_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_LOCAL 20 | memcached_return_t memcached_do(memcached_server_write_instance_st ptr, 21 | const void *commmand, 22 | size_t command_length, 23 | bool with_flush); 24 | 25 | LIBMEMCACHED_LOCAL 26 | memcached_return_t memcached_vdo(memcached_server_write_instance_st ptr, 27 | const struct libmemcached_io_vector_st *vector, size_t count, 28 | bool with_flush); 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif /* __LIBMEMCACHED_DO_H__ */ 35 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/dump.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Simple method for dumping data from Memcached. 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_DUMP_H__ 13 | #define __LIBMEMCACHED_DUMP_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_API 20 | memcached_return_t memcached_dump(memcached_st *ptr, memcached_dump_fn *function, void *context, uint32_t number_of_callbacks); 21 | 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif /* __LIBMEMCACHED_DUMP_H__ */ 28 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/exception.hpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Summary: Exceptions for the C++ interface 3 | * 4 | * Copy: See Copyright for the status of this software. 5 | * 6 | */ 7 | 8 | /** 9 | * @file 10 | * @brief Exception declarations 11 | */ 12 | 13 | #ifndef LIBMEMACHED_EXCEPTION_HPP 14 | #define LIBMEMACHED_EXCEPTION_HPP 15 | 16 | #include 17 | #include 18 | 19 | namespace memcache 20 | { 21 | class Exception : public std::runtime_error 22 | { 23 | public: 24 | Exception(const std::string& msg, int in_errno) 25 | : 26 | std::runtime_error(msg), 27 | _errno(in_errno) 28 | {} 29 | 30 | Exception(const char *msg, int in_errno) 31 | : 32 | std::runtime_error(std::string(msg)), 33 | _errno(in_errno) {} 34 | 35 | virtual ~Exception() throw() {} 36 | 37 | int getErrno() const 38 | { 39 | return _errno; 40 | } 41 | 42 | private: 43 | int _errno; 44 | }; 45 | 46 | class Warning : public Exception 47 | { 48 | public: 49 | Warning(const std::string& msg, int in_errno) : Exception(msg, in_errno) {} 50 | Warning(const char *msg, int in_errno) : Exception(msg, in_errno) {} 51 | }; 52 | 53 | class Error : public Exception 54 | { 55 | public: 56 | Error(const std::string& msg, int in_errno) : Exception(msg, in_errno) {} 57 | Error(const char *msg, int in_errno) : Exception(msg, in_errno) {} 58 | virtual ~Error() throw() {} 59 | }; 60 | 61 | } /* namespace libmemcached */ 62 | 63 | #endif /* LIBMEMACHED_EXCEPTION_HPP */ 64 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/fetch.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Work with fetching results 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_FETCH_H__ 13 | #define __LIBMEMCACHED_FETCH_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_API 20 | memcached_return_t memcached_fetch_execute(memcached_st *ptr, 21 | memcached_execute_fn *callback, 22 | void *context, 23 | uint32_t number_of_callbacks); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif /* __LIBMEMCACHED_FETCH_H__ */ 30 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/flush.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Flush connections. 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_FLUSH_H__ 13 | #define __LIBMEMCACHED_FLUSH_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_API 20 | memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif /* __LIBMEMCACHED_FLUSH_H__ */ 27 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/flush_buffers.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | memcached_return_t memcached_flush_buffers(memcached_st *memc) 4 | { 5 | memcached_return_t ret= MEMCACHED_SUCCESS; 6 | uint32_t x; 7 | 8 | for (x= 0; x < memcached_server_count(memc); ++x) 9 | { 10 | memcached_server_write_instance_st instance= 11 | memcached_server_instance_fetch(memc, x); 12 | 13 | if (instance->write_buffer_offset != 0) 14 | { 15 | if (instance->fd == -1 && 16 | (ret= memcached_connect(instance)) != MEMCACHED_SUCCESS) 17 | { 18 | WATCHPOINT_ERROR(ret); 19 | return ret; 20 | } 21 | 22 | if (memcached_io_write(instance, NULL, 0, true) == -1) 23 | { 24 | ret= MEMCACHED_SOME_ERRORS; 25 | } 26 | } 27 | } 28 | 29 | return ret; 30 | } 31 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/flush_buffers.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Work with fetching results 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_FLUSH_BUFFERS_H__ 13 | #define __LIBMEMCACHED_FLUSH_BUFFERS_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_API 20 | memcached_return_t memcached_flush_buffers(memcached_st *mem); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif /* __LIBMEMCACHED_FLUSH_BUFFERS_H__ */ 27 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/hash.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: hash interface code 9 | * 10 | */ 11 | 12 | #ifndef __MEMCACHED_HASH_H__ 13 | #define __MEMCACHED_HASH_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | /* The two public hash bits */ 20 | LIBMEMCACHED_API 21 | uint32_t memcached_generate_hash_value(const char *key, size_t key_length, memcached_hash_t hash_algorithm); 22 | 23 | LIBMEMCACHED_API 24 | const hashkit_st *memcached_get_hashkit(const memcached_st *ptr); 25 | 26 | LIBMEMCACHED_API 27 | memcached_return_t memcached_set_hashkit(memcached_st *ptr, hashkit_st *hashk); 28 | 29 | LIBMEMCACHED_API 30 | uint32_t memcached_generate_hash(const memcached_st *ptr, const char *key, size_t key_length); 31 | 32 | LIBMEMCACHED_LOCAL 33 | uint32_t memcached_generate_hash_with_redistribution(memcached_st *ptr, const char *key, size_t key_length); 34 | 35 | LIBMEMCACHED_API 36 | void memcached_autoeject(memcached_st *ptr); 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | 42 | #endif /* __MEMCACHED_HASH_H__ */ 43 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/internal.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Internal functions used by the library. Not for public use! 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_INTERNAL_H__ 13 | #define __LIBMEMCACHED_INTERNAL_H__ 14 | 15 | #if defined(BUILDING_LIBMEMCACHED) 16 | 17 | #ifdef __cplusplus 18 | extern "C" { 19 | #endif 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif /* BUILDING_LIBMEMCACHED */ 26 | #endif /* __LIBMEMCACHED_INTERNAL_H__ */ 27 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/key.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | memcached_return_t memcached_validate_key_length(size_t key_length, bool binary) 4 | { 5 | unlikely (key_length == 0) 6 | return MEMCACHED_BAD_KEY_PROVIDED; 7 | 8 | if (binary) 9 | { 10 | unlikely (key_length > 0xffff) 11 | return MEMCACHED_BAD_KEY_PROVIDED; 12 | } 13 | else 14 | { 15 | unlikely (key_length >= MEMCACHED_MAX_KEY) 16 | return MEMCACHED_BAD_KEY_PROVIDED; 17 | } 18 | 19 | return MEMCACHED_SUCCESS; 20 | } 21 | 22 | 23 | memcached_return_t memcached_key_test(const char * const *keys, 24 | const size_t *key_length, 25 | size_t number_of_keys) 26 | { 27 | uint32_t x; 28 | memcached_return_t rc; 29 | 30 | for (x= 0; x < number_of_keys; x++) 31 | { 32 | size_t y; 33 | 34 | rc= memcached_validate_key_length(*(key_length + x), false); 35 | if (rc != MEMCACHED_SUCCESS) 36 | return rc; 37 | 38 | for (y= 0; y < *(key_length + x); y++) 39 | { 40 | if ((isgraph(keys[x][y])) == 0) 41 | return MEMCACHED_BAD_KEY_PROVIDED; 42 | } 43 | } 44 | 45 | return MEMCACHED_SUCCESS; 46 | } 47 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/libmemcached_probes.d: -------------------------------------------------------------------------------- 1 | provider libmemcached { 2 | probe memcached_delete_start(); 3 | probe memcached_delete_end(); 4 | probe memcached_increment_with_initial_start(); 5 | probe memcached_increment_with_initial_end(); 6 | probe memcached_decrement_with_initial_start(); 7 | probe memcached_decrement_with_initial_end(); 8 | probe memcached_increment_start(); 9 | probe memcached_increment_end(); 10 | probe memcached_decrement_start(); 11 | probe memcached_decrement_end(); 12 | probe memcached_flush_start(); 13 | probe memcached_flush_end(); 14 | probe memcached_set_start(); 15 | probe memcached_set_end(); 16 | probe memcached_add_start(); 17 | probe memcached_add_end(); 18 | probe memcached_replace_start(); 19 | probe memcached_replace_end(); 20 | probe memcached_get_start(); 21 | probe memcached_get_end(); 22 | probe memcached_mget_start(); 23 | probe memcached_mget_end(); 24 | probe memcached_connect_start(); 25 | probe memcached_connect_end(); 26 | probe memcached_server_add_start(); 27 | probe memcached_server_add_end(); 28 | }; 29 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/memcached/README.txt: -------------------------------------------------------------------------------- 1 | For your convenience libmemcached contains a copy of protocol_binary.h so that 2 | you may compile libmemcached without having a memcached server with support 3 | for the binary protocol installed on your computer. Please do not modify this 4 | fine, but replace it with a fresh copy from a new distribution if they are 5 | out of sync. 6 | 7 | Trond Norbye 8 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/memcached_util.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Connection pool library. 9 | * 10 | * Author: Trond Norbye, Brian Aker 11 | * 12 | */ 13 | 14 | 15 | #ifndef __LIBMEMCACHED__MEMCACHED_UTIL_H__ 16 | #define __LIBMEMCACHED__MEMCACHED_UTIL_H__ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #endif /* __LIBMEMCACHED__MEMCACHED_UTIL_H__ */ 23 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/parse.c: -------------------------------------------------------------------------------- 1 | /* 2 | I debated about putting this in the client library since it does an 3 | action I don't really believe belongs in the library. 4 | 5 | Frankly its too damn useful not to be here though. 6 | */ 7 | 8 | #include "common.h" 9 | 10 | memcached_server_list_st memcached_servers_parse(const char *server_strings) 11 | { 12 | char *string; 13 | in_port_t port; 14 | uint32_t weight; 15 | const char *begin_ptr; 16 | const char *end_ptr; 17 | memcached_server_st *servers= NULL; 18 | memcached_return_t rc; 19 | 20 | WATCHPOINT_ASSERT(server_strings); 21 | 22 | end_ptr= server_strings + strlen(server_strings); 23 | 24 | for (begin_ptr= server_strings, string= index(server_strings, ','); 25 | begin_ptr != end_ptr; 26 | string= index(begin_ptr, ',')) 27 | { 28 | char buffer[HUGE_STRING_LEN]; 29 | char *ptr, *ptr2; 30 | port= 0; 31 | weight= 0; 32 | 33 | if (string) 34 | { 35 | memcpy(buffer, begin_ptr, (size_t) (string - begin_ptr)); 36 | buffer[(unsigned int)(string - begin_ptr)]= 0; 37 | begin_ptr= string+1; 38 | } 39 | else 40 | { 41 | size_t length= strlen(begin_ptr); 42 | memcpy(buffer, begin_ptr, length); 43 | buffer[length]= 0; 44 | begin_ptr= end_ptr; 45 | } 46 | 47 | ptr= index(buffer, ':'); 48 | 49 | if (ptr) 50 | { 51 | ptr[0]= 0; 52 | 53 | ptr++; 54 | 55 | port= (in_port_t) strtoul(ptr, (char **)NULL, 10); 56 | 57 | ptr2= index(ptr, ' '); 58 | if (! ptr2) 59 | ptr2= index(ptr, ':'); 60 | if (ptr2) 61 | { 62 | ptr2++; 63 | weight = (uint32_t) strtoul(ptr2, (char **)NULL, 10); 64 | } 65 | } 66 | 67 | servers= memcached_server_list_append_with_weight(servers, buffer, port, weight, &rc); 68 | 69 | if (isspace(*begin_ptr)) 70 | begin_ptr++; 71 | } 72 | 73 | return servers; 74 | } 75 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/parse.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Work with fetching results 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_PARSE_H__ 13 | #define __LIBMEMCACHED_PARSE_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_API 20 | memcached_server_list_st memcached_servers_parse(const char *server_strings); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif /* __LIBMEMCACHED_PARSE_H__ */ 27 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/platform.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2010 Brian Aker, Trond Norbye 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Try to hide platform-specific stuff 9 | * 10 | */ 11 | #ifndef LIBMEMCACHED_PLATFORM_H 12 | #define LIBMEMCACHED_PLATFORM_H 1 13 | 14 | #ifdef WIN32 15 | 16 | #include 17 | #include 18 | typedef short in_port_t; 19 | typedef SOCKET memcached_socket_t; 20 | #else 21 | typedef int memcached_socket_t; 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #endif /* WIN32 */ 30 | 31 | 32 | #endif /* LIBMEMCACHED_PLATFORM_H */ 33 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/quit.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: returns a human readable string for the error message 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_QUIT_H__ 13 | #define __LIBMEMCACHED_QUIT_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_API 20 | void memcached_quit(memcached_st *ptr); 21 | 22 | LIBMEMCACHED_LOCAL 23 | void memcached_quit_server(memcached_server_st *ptr, bool io_death); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif /* __LIBMEMCACHED_QUIT_H__ */ 30 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/response.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Change the behavior of the memcached connection. 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_RESPONSE_H__ 13 | #define __LIBMEMCACHED_RESPONSE_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | /* Read a single response from the server */ 20 | LIBMEMCACHED_LOCAL 21 | memcached_return_t memcached_read_one_response(memcached_server_write_instance_st ptr, 22 | char *buffer, size_t buffer_length, 23 | memcached_result_st *result); 24 | 25 | LIBMEMCACHED_LOCAL 26 | memcached_return_t memcached_response(memcached_server_write_instance_st ptr, 27 | char *buffer, size_t buffer_length, 28 | memcached_result_st *result); 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | 34 | #endif /* __LIBMEMCACHED_RESPONSE_H__ */ 35 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/result.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Functions to manipulate the result structure. 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_RESULT_H__ 13 | #define __LIBMEMCACHED_RESULT_H__ 14 | 15 | struct memcached_result_st { 16 | uint32_t item_flags; 17 | time_t item_expiration; 18 | size_t key_length; 19 | uint64_t item_cas; 20 | const memcached_st *root; 21 | memcached_string_st value; 22 | char item_key[MEMCACHED_MAX_KEY]; 23 | struct { 24 | bool is_allocated:1; 25 | bool is_initialized:1; 26 | } options; 27 | /* Add result callback function */ 28 | }; 29 | 30 | #ifdef __cplusplus 31 | extern "C" { 32 | #endif 33 | 34 | /* Result Struct */ 35 | LIBMEMCACHED_API 36 | void memcached_result_free(memcached_result_st *result); 37 | 38 | LIBMEMCACHED_API 39 | void memcached_result_reset(memcached_result_st *ptr); 40 | 41 | LIBMEMCACHED_API 42 | memcached_result_st *memcached_result_create(const memcached_st *ptr, 43 | memcached_result_st *result); 44 | 45 | LIBMEMCACHED_API 46 | const char *memcached_result_key_value(const memcached_result_st *self); 47 | 48 | LIBMEMCACHED_API 49 | size_t memcached_result_key_length(const memcached_result_st *self); 50 | 51 | LIBMEMCACHED_API 52 | const char *memcached_result_value(const memcached_result_st *self); 53 | 54 | LIBMEMCACHED_API 55 | size_t memcached_result_length(const memcached_result_st *self); 56 | 57 | LIBMEMCACHED_API 58 | uint32_t memcached_result_flags(const memcached_result_st *self); 59 | 60 | LIBMEMCACHED_API 61 | uint64_t memcached_result_cas(const memcached_result_st *self); 62 | 63 | LIBMEMCACHED_API 64 | memcached_return_t memcached_result_set_value(memcached_result_st *ptr, const char *value, size_t length); 65 | 66 | LIBMEMCACHED_API 67 | void memcached_result_set_flags(memcached_result_st *self, uint32_t flags); 68 | 69 | LIBMEMCACHED_API 70 | void memcached_result_set_expiration(memcached_result_st *self, time_t expiration); 71 | 72 | #ifdef __cplusplus 73 | } /* extern "C" */ 74 | #endif 75 | 76 | 77 | #endif /* __LIBMEMCACHED_RESULT_H__ */ 78 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/sasl.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: interface for memcached server 9 | * Description: main include file for libmemcached 10 | * 11 | */ 12 | #ifndef LIBMEMCACHED_MEMCACHED_SASL_H 13 | #define LIBMEMCACHED_MEMCACHED_SASL_H 14 | 15 | #ifdef LIBMEMCACHED_WITH_SASL_SUPPORT 16 | #include 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | LIBMEMCACHED_API 23 | void memcached_set_sasl_callbacks(memcached_st *ptr, 24 | const sasl_callback_t *callbacks); 25 | 26 | LIBMEMCACHED_API 27 | memcached_return_t memcached_set_sasl_auth_data(memcached_st *ptr, 28 | const char *username, 29 | const char *password); 30 | 31 | LIBMEMCACHED_API 32 | memcached_return_t memcached_destroy_sasl_auth_data(memcached_st *ptr); 33 | 34 | 35 | LIBMEMCACHED_API 36 | const sasl_callback_t *memcached_get_sasl_callbacks(memcached_st *ptr); 37 | 38 | LIBMEMCACHED_LOCAL 39 | memcached_return_t memcached_clone_sasl(memcached_st *clone, const memcached_st *source); 40 | 41 | LIBMEMCACHED_LOCAL 42 | memcached_return_t memcached_sasl_authenticate_connection(memcached_server_st *server); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif /* LIBMEMCACHED_WITH_SASL_SUPPORT */ 49 | 50 | struct memcached_sasl_st { 51 | #ifdef LIBMEMCACHED_WITH_SASL_SUPPORT 52 | const sasl_callback_t *callbacks; 53 | #else 54 | const void *callbacks; 55 | #endif 56 | /* 57 | ** Did we allocate data inside the callbacks, or did the user 58 | ** supply that. 59 | */ 60 | bool is_allocated; 61 | }; 62 | 63 | 64 | 65 | #endif /* LIBMEMCACHED_MEMCACHED_SASL_H */ 66 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/server_list.c: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: 9 | * 10 | */ 11 | 12 | 13 | #include "common.h" 14 | 15 | memcached_server_list_st 16 | memcached_server_list_append_with_weight(memcached_server_list_st ptr, 17 | const char *hostname, in_port_t port, 18 | uint32_t weight, 19 | memcached_return_t *error) 20 | { 21 | uint32_t count; 22 | memcached_server_list_st new_host_list; 23 | 24 | if (hostname == NULL || error == NULL) 25 | return NULL; 26 | 27 | if (! port) 28 | port= MEMCACHED_DEFAULT_PORT; 29 | 30 | /* Increment count for hosts */ 31 | count= 1; 32 | if (ptr != NULL) 33 | { 34 | count+= memcached_server_list_count(ptr); 35 | } 36 | 37 | new_host_list= (memcached_server_write_instance_st)realloc(ptr, sizeof(memcached_server_st) * count); 38 | if (!new_host_list) 39 | { 40 | ptr->cached_errno= errno; 41 | *error= MEMCACHED_MEMORY_ALLOCATION_FAILURE; 42 | return NULL; 43 | } 44 | 45 | /* TODO: Check return type */ 46 | memcached_server_create_with(NULL, &new_host_list[count-1], hostname, port, weight, MEMCACHED_CONNECTION_TCP); 47 | 48 | /* Backwards compatibility hack */ 49 | memcached_servers_set_count(new_host_list, count); 50 | 51 | *error= MEMCACHED_SUCCESS; 52 | return new_host_list; 53 | } 54 | 55 | memcached_server_list_st 56 | memcached_server_list_append(memcached_server_list_st ptr, 57 | const char *hostname, in_port_t port, 58 | memcached_return_t *error) 59 | { 60 | return memcached_server_list_append_with_weight(ptr, hostname, port, 0, error); 61 | } 62 | 63 | uint32_t memcached_server_list_count(const memcached_server_list_st self) 64 | { 65 | return (self == NULL) 66 | ? 0 67 | : self->number_of_hosts; 68 | } 69 | 70 | memcached_server_st *memcached_server_list(const memcached_st *self) 71 | { 72 | return self->servers; 73 | } 74 | 75 | void memcached_server_list_set(memcached_st *self, memcached_server_st *list) 76 | { 77 | self->servers= list; 78 | } 79 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/server_list.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Types for libmemcached 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_SERVER_LIST_H__ 13 | #define __LIBMEMCACHED_SERVER_LIST_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | /* Server List Public functions */ 20 | LIBMEMCACHED_API 21 | void memcached_server_list_free(memcached_server_list_st ptr); 22 | 23 | LIBMEMCACHED_API 24 | memcached_return_t memcached_server_push(memcached_st *ptr, const memcached_server_list_st list); 25 | 26 | LIBMEMCACHED_API 27 | memcached_server_list_st memcached_server_list_append(memcached_server_list_st ptr, 28 | const char *hostname, 29 | in_port_t port, 30 | memcached_return_t *error); 31 | LIBMEMCACHED_API 32 | memcached_server_list_st memcached_server_list_append_with_weight(memcached_server_list_st ptr, 33 | const char *hostname, 34 | in_port_t port, 35 | uint32_t weight, 36 | memcached_return_t *error); 37 | LIBMEMCACHED_API 38 | uint32_t memcached_server_list_count(const memcached_server_list_st ptr); 39 | 40 | LIBMEMCACHED_LOCAL 41 | uint32_t memcached_servers_set_count(memcached_server_list_st servers, uint32_t count); 42 | 43 | LIBMEMCACHED_LOCAL 44 | memcached_server_st *memcached_server_list(const memcached_st *); 45 | 46 | LIBMEMCACHED_LOCAL 47 | void memcached_server_list_set(memcached_st *self, memcached_server_list_st list); 48 | 49 | #ifdef __cplusplus 50 | } /* extern "C" */ 51 | #endif 52 | 53 | #endif /* __LIBMEMCACHED_SERVER_LIST_H__ */ 54 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/stats.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Collect up the stats for a memcached server. 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_STATS_H__ 13 | #define __LIBMEMCACHED_STATS_H__ 14 | 15 | struct memcached_stat_st { 16 | uint32_t connection_structures; 17 | uint32_t curr_connections; 18 | uint32_t curr_items; 19 | uint32_t pid; 20 | uint32_t pointer_size; 21 | uint32_t rusage_system_microseconds; 22 | uint32_t rusage_system_seconds; 23 | uint32_t rusage_user_microseconds; 24 | uint32_t rusage_user_seconds; 25 | uint32_t threads; 26 | uint32_t time; 27 | uint32_t total_connections; 28 | uint32_t total_items; 29 | uint32_t uptime; 30 | uint64_t bytes; 31 | uint64_t bytes_read; 32 | uint64_t bytes_written; 33 | uint64_t cmd_get; 34 | uint64_t cmd_set; 35 | uint64_t evictions; 36 | uint64_t get_hits; 37 | uint64_t get_misses; 38 | uint64_t limit_maxbytes; 39 | char version[MEMCACHED_VERSION_STRING_LENGTH]; 40 | memcached_st *root; 41 | }; 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | LIBMEMCACHED_API 48 | void memcached_stat_free(const memcached_st *, memcached_stat_st *); 49 | 50 | LIBMEMCACHED_API 51 | memcached_stat_st *memcached_stat(memcached_st *ptr, char *args, memcached_return_t *error); 52 | 53 | LIBMEMCACHED_API 54 | memcached_return_t memcached_stat_servername(memcached_stat_st *memc_stat, char *args, 55 | const char *hostname, in_port_t port); 56 | 57 | LIBMEMCACHED_API 58 | char *memcached_stat_get_value(const memcached_st *ptr, memcached_stat_st *memc_stat, 59 | const char *key, memcached_return_t *error); 60 | 61 | LIBMEMCACHED_API 62 | char ** memcached_stat_get_keys(const memcached_st *ptr, memcached_stat_st *memc_stat, 63 | memcached_return_t *error); 64 | 65 | LIBMEMCACHED_API 66 | memcached_return_t memcached_stat_execute(memcached_st *memc, const char *args, memcached_stat_fn func, void *context); 67 | 68 | #ifdef __cplusplus 69 | } 70 | #endif 71 | 72 | #endif /* __LIBMEMCACHED_STATS_H__ */ 73 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/strerror.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: returns a human readable string for the error message 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_STRERROR_H__ 13 | #define __LIBMEMCACHED_STRERROR_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_API 20 | const char *memcached_strerror(memcached_st *ptr, memcached_return_t rc); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif /* __LIBMEMCACHED_STRERROR_H__ */ 27 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/string.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: String structure used for libmemcached. 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_STRING_H__ 13 | #define __LIBMEMCACHED_STRING_H__ 14 | 15 | /** 16 | Strings are always under our control so we make some assumptions 17 | about them. 18 | 19 | 1) is_initialized is always valid. 20 | 2) A string once intialized will always be, until free where we 21 | unset this flag. 22 | 3) A string always has a root. 23 | */ 24 | 25 | struct memcached_string_st { 26 | char *end; 27 | char *string; 28 | size_t current_size; 29 | const memcached_st *root; 30 | struct { 31 | bool is_allocated:1; 32 | bool is_initialized:1; 33 | } options; 34 | }; 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | LIBMEMCACHED_LOCAL 41 | memcached_string_st *memcached_string_create(const memcached_st *ptr, 42 | memcached_string_st *string, 43 | size_t initial_size); 44 | LIBMEMCACHED_LOCAL 45 | memcached_return_t memcached_string_check(memcached_string_st *string, size_t need); 46 | 47 | LIBMEMCACHED_LOCAL 48 | char *memcached_string_c_copy(memcached_string_st *string); 49 | 50 | LIBMEMCACHED_LOCAL 51 | memcached_return_t memcached_string_append_character(memcached_string_st *string, 52 | char character); 53 | LIBMEMCACHED_LOCAL 54 | memcached_return_t memcached_string_append(memcached_string_st *string, 55 | const char *value, size_t length); 56 | LIBMEMCACHED_LOCAL 57 | memcached_return_t memcached_string_reset(memcached_string_st *string); 58 | 59 | LIBMEMCACHED_LOCAL 60 | void memcached_string_free(memcached_string_st *string); 61 | 62 | LIBMEMCACHED_LOCAL 63 | size_t memcached_string_length(const memcached_string_st *self); 64 | 65 | LIBMEMCACHED_LOCAL 66 | size_t memcached_string_size(const memcached_string_st *self); 67 | 68 | LIBMEMCACHED_LOCAL 69 | const char *memcached_string_value(const memcached_string_st *self); 70 | 71 | LIBMEMCACHED_LOCAL 72 | char *memcached_string_value_mutable(const memcached_string_st *self); 73 | 74 | LIBMEMCACHED_LOCAL 75 | void memcached_string_set_length(memcached_string_st *self, size_t length); 76 | 77 | #ifdef __cplusplus 78 | } 79 | #endif 80 | 81 | 82 | #endif /* __LIBMEMCACHED_STRING_H__ */ 83 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/util.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Connection pool library. 9 | * 10 | * Author: Trond Norbye, Brian Aker 11 | * 12 | */ 13 | 14 | 15 | #ifndef __LIBMEMCACHED__UTIL_H__ 16 | #define __LIBMEMCACHED__UTIL_H__ 17 | 18 | #include 19 | 20 | #endif /* __LIBMEMCACHED__UTIL_H__ */ 21 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/verbosity.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | 3 | struct context_st 4 | { 5 | size_t length; 6 | const char *buffer; 7 | }; 8 | 9 | static memcached_return_t _set_verbosity(const memcached_st *ptr, 10 | const memcached_server_st *server, 11 | void *context) 12 | { 13 | memcached_return_t rc; 14 | memcached_st local_memc; 15 | memcached_st *memc_ptr; 16 | char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; 17 | 18 | struct context_st *execute= (struct context_st *)context; 19 | (void)ptr; 20 | 21 | memc_ptr= memcached_create(&local_memc); 22 | 23 | rc= memcached_server_add(memc_ptr, memcached_server_name(server), memcached_server_port(server)); 24 | 25 | if (rc == MEMCACHED_SUCCESS) 26 | { 27 | memcached_server_write_instance_st instance= 28 | memcached_server_instance_fetch(memc_ptr, 0); 29 | 30 | rc= memcached_do(instance, execute->buffer, execute->length, true); 31 | 32 | if (rc == MEMCACHED_SUCCESS) 33 | { 34 | rc= memcached_response(instance, buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, NULL); 35 | } 36 | } 37 | 38 | memcached_free(memc_ptr); 39 | 40 | return rc; 41 | } 42 | 43 | memcached_return_t memcached_verbosity(memcached_st *ptr, uint32_t verbosity) 44 | { 45 | int send_length; 46 | memcached_server_fn callbacks[1]; 47 | struct context_st context; 48 | char buffer[MEMCACHED_DEFAULT_COMMAND_SIZE]; 49 | 50 | send_length= snprintf(buffer, MEMCACHED_DEFAULT_COMMAND_SIZE, 51 | "verbosity %u\r\n", verbosity); 52 | if (send_length >= MEMCACHED_DEFAULT_COMMAND_SIZE || send_length < 0) 53 | return MEMCACHED_WRITE_FAILURE; 54 | 55 | memset(&context, 0, sizeof(context)); 56 | context.length= (size_t)send_length; 57 | context.buffer= buffer; 58 | 59 | callbacks[0]= _set_verbosity; 60 | 61 | return memcached_server_cursor(ptr, callbacks, &context, 1); 62 | } 63 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/verbosity.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Change the verbository level of the memcached server 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_VERBOSITY_H__ 13 | #define __LIBMEMCACHED_VERBOSITY_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_API 20 | memcached_return_t memcached_verbosity(memcached_st *ptr, uint32_t verbosity); 21 | 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif /* __LIBMEMCACHED_VERBOSITY_H__ */ 28 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/version.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Find version information 9 | * 10 | */ 11 | 12 | #ifndef __LIBMEMCACHED_VERSION_H__ 13 | #define __LIBMEMCACHED_VERSION_H__ 14 | 15 | #ifdef __cplusplus 16 | extern "C" { 17 | #endif 18 | 19 | LIBMEMCACHED_API 20 | memcached_return_t memcached_version(memcached_st *ptr); 21 | 22 | LIBMEMCACHED_API 23 | const char * memcached_lib_version(void); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | 29 | #endif /* __LIBMEMCACHED_VERSION_H__ */ 30 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/visibility.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2006-2009 Brian Aker 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Interface for memcached server. 9 | * 10 | * Author: Trond Norbye 11 | * 12 | */ 13 | 14 | /** 15 | * @file 16 | * @brief Visibility control macros 17 | */ 18 | 19 | #ifndef __LIBMEMCACHED_VISIBILITY_H__ 20 | #define __LIBMEMCACHED_VISIBILITY_H__ 21 | 22 | /** 23 | * 24 | * LIBMEMCACHED_API is used for the public API symbols. It either DLL imports or 25 | * DLL exports (or does nothing for static build). 26 | * 27 | * LIBMEMCACHED_LOCAL is used for non-api symbols. 28 | */ 29 | 30 | #if defined(BUILDING_LIBMEMCACHED) 31 | # if defined(HAVE_VISIBILITY) && HAVE_VISIBILITY 32 | # define LIBMEMCACHED_API __attribute__ ((visibility("default"))) 33 | # define LIBMEMCACHED_LOCAL __attribute__ ((visibility("hidden"))) 34 | # elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550) 35 | # define LIBMEMCACHED_API __global 36 | # define LIBMEMCACHED_LOCAL __hidden 37 | # elif defined(_MSC_VER) 38 | # define LIBMEMCACHED_API extern __declspec(dllexport) 39 | # define LIBMEMCACHED_LOCAL 40 | # else 41 | # define LIBMEMCACHED_API 42 | # define LIBMEMCACHED_LOCAL 43 | # endif /* defined(HAVE_VISIBILITY) */ 44 | #else /* defined(BUILDING_LIBMEMCACHED) */ 45 | # if defined(_MSC_VER) 46 | # define LIBMEMCACHED_API extern __declspec(dllimport) 47 | # define LIBMEMCACHED_LOCAL 48 | # else 49 | # define LIBMEMCACHED_API 50 | # define LIBMEMCACHED_LOCAL 51 | # endif /* defined(_MSC_VER) */ 52 | #endif /* defined(BUILDING_LIBMEMCACHED) */ 53 | 54 | #endif /* __LIBMEMCACHED_VISIBILITY_H__ */ 55 | -------------------------------------------------------------------------------- /libmemcached/libmemcached/win32.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | int win_gettimeofday(struct timeval *t) { 6 | memset(t, 0, sizeof(*t)); 7 | t->tv_sec = (long)time(NULL); 8 | return 0; 9 | } 10 | 11 | #undef getsockopt 12 | int win_getsockopt(SOCKET s, int level, int optname, void *value, socklen_t *option_len) 13 | { 14 | return getsockopt(s, level, optname, value, option_len); 15 | } 16 | 17 | #undef setsockopt 18 | int win_setsockopt(SOCKET s, int level, int optname, const void *value, socklen_t option_len) 19 | { 20 | return setsockopt(s, level, optname, value, option_len); 21 | } -------------------------------------------------------------------------------- /libmemcached/libmemcached_config.h.in: -------------------------------------------------------------------------------- 1 | #ifndef CONFIG_H 2 | #define CONFIG_H 3 | 4 | /* _SYS_FEATURE_TESTS_H is Solaris, _FEATURES_H is GCC */ 5 | #if defined( _SYS_FEATURE_TESTS_H) || defined(_FEATURES_H) 6 | #error "You should include config.h as your first include file" 7 | #endif 8 | 9 | #ifdef WIN32 10 | /* Windows specific section */ 11 | #include 12 | #include 13 | #include 14 | 15 | #else 16 | 17 | #ifndef __APPLE__ 18 | #define HAVE_MSG_NOSIGNAL 1 19 | #define HAVE_MSG_DONTWAIT 1 20 | #define TIME_WITH_SYS_TIME 1 21 | #endif 22 | 23 | #define HAVE_SYS_TIME_H 1 24 | #define HAVE_SYS_TYPES_H 1 25 | 26 | /* Define to 1 or 0, depending whether the compiler supports simple visibility 27 | declarations. */ 28 | #define HAVE_VISIBILITY 1 29 | 30 | #endif 31 | 32 | 33 | #ifdef __sun 34 | #define HAVE_HTONLL 1 35 | #define MSG_NOSIGNAL 0 36 | #endif 37 | 38 | #include 39 | #include 40 | 41 | /* To hide the platform differences between MS Windows and Unix, I am 42 | * going to use the Microsoft way and #define the Microsoft-specific 43 | * functions to the unix way. Microsoft use a separate subsystem for sockets, 44 | * but Unix normally just use a filedescriptor on the same functions. It is 45 | * a lot easier to map back to the unix way with macros than going the other 46 | * way without side effect ;-) 47 | */ 48 | #ifdef WIN32 49 | #include "win32/wrappers.h" 50 | /* #include "poll/poll.h" */ 51 | #define random() rand() 52 | #define srandom(a) srand(a) 53 | #define get_socket_errno() WSAGetLastError() 54 | 55 | /* Are these correct? */ 56 | # define SHUT_RD SD_RECEIVE 57 | # define SHUT_WR SD_SEND 58 | # define SHUT_RDWR SD_BOTH 59 | 60 | #else 61 | #include 62 | #define INVALID_SOCKET -1 63 | #define SOCKET_ERROR -1 64 | #define closesocket(a) close(a) 65 | #define get_socket_errno() errno 66 | 67 | #include 68 | 69 | #endif 70 | 71 | #ifndef HAVE_MSG_NOSIGNAL 72 | #define MSG_NOSIGNAL 0 73 | #endif 74 | 75 | #ifndef HAVE_MSG_DONTWAIT 76 | #define MSG_DONTWAIT 0 77 | #endif 78 | 79 | #cmakedefine HAVE_HTONLL ${HAVE_HTONLL} 80 | 81 | #endif 82 | -------------------------------------------------------------------------------- /libmemcached/poll/poll.c: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker, Trond Norbye 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Implementation of poll by using select 9 | * 10 | */ 11 | #include "libmemcached_config.h" 12 | #include 13 | #include 14 | 15 | int poll(struct pollfd fds[], nfds_t nfds, int tmo) 16 | { 17 | fd_set readfds, writefds, errorfds; 18 | FD_ZERO(&readfds); 19 | FD_ZERO(&writefds); 20 | FD_ZERO(&errorfds); 21 | 22 | int maxfd= 0; 23 | 24 | for (nfds_t x= 0; x < nfds; ++x) 25 | { 26 | if (fds[x].events & (POLLIN | POLLOUT)) 27 | { 28 | #ifndef WIN32 29 | if (fds[x].fd > maxfd) 30 | { 31 | maxfd= fds[x].fd; 32 | } 33 | #endif 34 | if (fds[x].events & POLLIN) 35 | { 36 | FD_SET(fds[x].fd, &readfds); 37 | } 38 | if (fds[x].events & POLLOUT) 39 | { 40 | FD_SET(fds[x].fd, &writefds); 41 | } 42 | } 43 | } 44 | 45 | struct timeval timeout= { .tv_sec = tmo / 1000, 46 | .tv_usec= (tmo % 1000) * 1000 }; 47 | struct timeval *tp= &timeout; 48 | if (tmo == -1) 49 | { 50 | tp= NULL; 51 | } 52 | int ret= select(maxfd + 1, &readfds, &writefds, &errorfds, tp); 53 | if (ret <= 0) 54 | { 55 | return ret; 56 | } 57 | 58 | /* Iterate through all of them because I need to clear the revent map */ 59 | for (nfds_t x= 0; x < nfds; ++x) 60 | { 61 | fds[x].revents= 0; 62 | if (FD_ISSET(fds[x].fd, &readfds)) 63 | { 64 | fds[x].revents |= POLLIN; 65 | } 66 | if (FD_ISSET(fds[x].fd, &writefds)) 67 | { 68 | fds[x].revents |= POLLOUT; 69 | } 70 | if (FD_ISSET(fds[x].fd, &errorfds)) 71 | { 72 | fds[x].revents |= POLLERR; 73 | } 74 | } 75 | 76 | return ret; 77 | } 78 | -------------------------------------------------------------------------------- /libmemcached/poll/poll.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker, Trond Norbye 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: Implementation of poll by using select 9 | * 10 | */ 11 | #ifndef POLL_POLL_H 12 | #define POLL_POLL_H 1 13 | 14 | #ifdef WIN32 15 | #include 16 | #endif 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif 21 | 22 | typedef struct pollfd 23 | { 24 | #ifdef WIN32 25 | SOCKET fd; 26 | #else 27 | int fd; 28 | #endif 29 | short events; 30 | short revents; 31 | } pollfd_t; 32 | 33 | typedef int nfds_t; 34 | 35 | #define POLLIN 0x0001 36 | #define POLLOUT 0x0004 37 | #define POLLERR 0x0008 38 | 39 | int poll(struct pollfd fds[], nfds_t nfds, int tmo); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /libmemcached/win32/inttypes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | -------------------------------------------------------------------------------- /libmemcached/win32/stdbool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef __cplusplus 4 | #ifndef bool 5 | #define _Bool bool 6 | #define bool char 7 | #define false 0 8 | #define true 1 9 | #endif 10 | #endif 11 | -------------------------------------------------------------------------------- /libmemcached/win32/stdint.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | typedef __int8 int8_t; 5 | typedef __int16 int13_t; 6 | typedef __int32 int32_t; 7 | typedef __int64 int64_t; 8 | 9 | typedef unsigned __int8 uint8_t; 10 | typedef unsigned __int16 uint16_t; 11 | typedef unsigned __int32 uint32_t; 12 | typedef unsigned __int64 uint64_t; 13 | 14 | typedef long ssize_t; 15 | 16 | #define UINT8_MAX _UI8_MAX 17 | #define UINT32_MAX _UI32_MAX 18 | #define UINT64_C(val) val##ui64 19 | -------------------------------------------------------------------------------- /libmemcached/win32/strings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | -------------------------------------------------------------------------------- /libmemcached/win32/sys/time.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | -------------------------------------------------------------------------------- /libmemcached/win32/unistd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | -------------------------------------------------------------------------------- /libmemcached/win32/wrappers.h: -------------------------------------------------------------------------------- 1 | /* LibMemcached 2 | * Copyright (C) 2010 Brian Aker, Trond Norbye 3 | * All rights reserved. 4 | * 5 | * Use and distribution licensed under the BSD license. See 6 | * the COPYING file in the parent directory for full text. 7 | * 8 | * Summary: "Implementation" of the function we don't have on windows 9 | * to avoid a bunch of ifdefs in the rest of the code 10 | * 11 | */ 12 | #ifndef WIN32_WRAPPERS_H 13 | #define WIN32_WRAPPERS_H 1 14 | 15 | #include 16 | 17 | /* 18 | * One of the Windows headers define interface as a macro, but that 19 | * is causing problems with the member named "interface" in some of the 20 | * structs. 21 | */ 22 | #undef interface 23 | 24 | #undef malloc 25 | #undef realloc 26 | 27 | #if _MSC_VER < 1900 28 | #define snprintf _snprintf 29 | #endif 30 | #define PRIu64 "I64u" 31 | 32 | #define poll(a,b,c) WSAPoll(a,b,c) 33 | 34 | #define gettimeofday(a, b) win_gettimeofday(a) 35 | extern int win_gettimeofday(struct timeval *t); 36 | #define strdup(a) _strdup(a) 37 | #define strtoull(a, b, c) _strtoui64(a, b, c) 38 | #define strtoll(a, b, c) _strtoi64(a, b, c) 39 | 40 | #define getsockopt(a, b, c, d, e) win_getsockopt(a, b, c, d, e) 41 | extern int win_getsockopt(SOCKET s, int level, int optname, void *value, socklen_t *option_len); 42 | 43 | #define setsockopt(a, b, c, d, e) win_setsockopt(a, b, c, d, e) 44 | extern int win_setsockopt(SOCKET s, int level, int optname, const void *value, socklen_t option_len); 45 | 46 | #if 0 47 | /* 48 | * WinSock use a separate range for error codes. Let's just map to the 49 | * WinSock ones. 50 | */ 51 | #define EADDRINUSE WSAEADDRINUSE 52 | #define EWOULDBLOCK WSAEWOULDBLOCK 53 | #define EINPROGRESS WSAEINPROGRESS 54 | #define EALREADY WSAEALREADY 55 | #define EISCONN WSAEISCONN 56 | #define ENOTCONN WSAENOTCONN 57 | #define ENOBUFS WSAENOBUFS 58 | #define SHUT_RDWR SD_BOTH 59 | #endif 60 | 61 | /* EAI_SYSTEM isn't defined anywhere... just set it to... 11? */ 62 | #define EAI_SYSTEM 11 63 | 64 | /* Best effort mapping of functions to alternative functions */ 65 | #define index(a,b) strchr(a,b) 66 | #define rindex(a,b) strrchr(a,b) 67 | #define random() rand() 68 | #define kill(a, b) while (false) {} 69 | #define fork() (-1) 70 | #define waitpid(a,b,c) (-1) 71 | #define fnmatch(a,b,c) (-1) 72 | #define sleep(a) Sleep(a*1000) 73 | 74 | #endif /* WIN32_WRAPPERS_H */ 75 | -------------------------------------------------------------------------------- /scripts/dtrace-profile.d: -------------------------------------------------------------------------------- 1 | /* Count function invocations. 2 | * 3 | * usage: 4 | * sudo dtrace -q -s dtrace-profile.d PID 5 | */ 6 | 7 | pid$1:::entry 8 | { 9 | self->t[probefunc] = timestamp; 10 | } 11 | 12 | pid$1:::return 13 | / self->t[probefunc] != 0 / 14 | { 15 | @counts[probemod, probefunc] = sum(timestamp - self->t[probefunc]); 16 | } 17 | 18 | tick-5s 19 | { 20 | printa(@counts); 21 | } 22 | -------------------------------------------------------------------------------- /scripts/dtrace-syscalls.d: -------------------------------------------------------------------------------- 1 | /* Trace all the syscalls invoked during a given C function. 2 | * 3 | * usage: 4 | * sudo dtrace -q -s dtrace-syscalls.d PID PROBEFUNC 5 | * 6 | * example: 7 | * sudo dtrace -q -s dtrace-syscalls.d 6666 try_read_command 8 | */ 9 | 10 | pid$1::$2:entry 11 | { 12 | printf("starting %s\n", probefunc); 13 | self->in_function = 1; 14 | ustack(); 15 | } 16 | 17 | pid$1::$2:return 18 | { 19 | printf("ending %s\n", probefunc); 20 | self->in_function = 0; 21 | } 22 | 23 | syscall::: 24 | / self->in_function != 0 / 25 | { 26 | printf("%s %s %s\n", execname, probefunc, probename); 27 | } 28 | 29 | 30 | -------------------------------------------------------------------------------- /scripts/examples/moxi.conf.direct: -------------------------------------------------------------------------------- 1 | 11211=memcached1.yourcorp.com:11211,memcached2.yourcorp.com:11211 2 | -------------------------------------------------------------------------------- /scripts/examples/moxi.conf.service: -------------------------------------------------------------------------------- 1 | apikey=my_user_id:my_password@memscale.ec2.northscale.net 2 | -------------------------------------------------------------------------------- /scripts/memcached-init: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # skeleton example file to build /etc/init.d/ scripts. 4 | # This file should be used to construct scripts for /etc/init.d. 5 | # 6 | # Written by Miquel van Smoorenburg . 7 | # Modified for Debian 8 | # by Ian Murdock . 9 | # 10 | # Version: @(#)skeleton 1.9 26-Feb-2001 miquels@cistron.nl 11 | # 12 | 13 | PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin 14 | DAEMON=/usr/bin/memcached 15 | DAEMONBOOTSTRAP=/usr/share/memcached/scripts/start-memcached 16 | NAME=memcached 17 | DESC=memcached 18 | PIDFILE=/var/run/$NAME.pid 19 | 20 | test -x $DAEMON || exit 0 21 | test -x $DAEMONBOOTSTRAP || exit 0 22 | 23 | set -e 24 | 25 | case "$1" in 26 | start) 27 | echo -n "Starting $DESC: " 28 | start-stop-daemon --start --quiet --exec $DAEMONBOOTSTRAP 29 | echo "$NAME." 30 | ;; 31 | stop) 32 | echo -n "Stopping $DESC: " 33 | start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE --exec $DAEMON 34 | echo "$NAME." 35 | rm -f $PIDFILE 36 | ;; 37 | 38 | restart|force-reload) 39 | # 40 | # If the "reload" option is implemented, move the "force-reload" 41 | # option to the "reload" entry above. If not, "force-reload" is 42 | # just the same as "restart". 43 | # 44 | echo -n "Restarting $DESC: " 45 | start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE 46 | rm -f $PIDFILE 47 | sleep 1 48 | start-stop-daemon --start --quiet --exec $DAEMONBOOTSTRAP 49 | echo "$NAME." 50 | ;; 51 | *) 52 | N=/etc/init.d/$NAME 53 | # echo "Usage: $N {start|stop|restart|reload|force-reload}" >&2 54 | echo "Usage: $N {start|stop|restart|force-reload}" >&2 55 | exit 1 56 | ;; 57 | esac 58 | 59 | exit 0 60 | -------------------------------------------------------------------------------- /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.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 | -------------------------------------------------------------------------------- /scripts/moxi-init.rhat.in: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # chkconfig: - 55 45 4 | # description: The moxi is a memchached proxy 5 | # processname: moxi 6 | # config: /etc/sysconfig/moxi 7 | 8 | # Source function library. 9 | . /etc/rc.d/init.d/functions 10 | 11 | USER=nobody 12 | MAXCONN=1024 13 | CPROXY_ARG=/etc/moxi.conf 14 | OPTIONS="" 15 | 16 | if [ -f /etc/sysconfig/moxi ];then 17 | . /etc/sysconfig/moxi 18 | fi 19 | 20 | # Check that networking is up. 21 | if [ "$NETWORKING" = "no" ] 22 | then 23 | exit 0 24 | fi 25 | 26 | # if CPROXY_ARG is a config file reference check it's existance 27 | if ([[ "/" < "$CPROXY_ARG" ]] && [[ "$CPROXY_ARG" < "0" ]]) || ([[ "." < "$CPROXY_ARG" ]] && [[ "$CPROXY_ARG" < "/" ]]); then 28 | if [ ! -f "$CPROXY_ARG" ]; then 29 | echo "Misconfiguration! '$CPROXY_ARG' is absent. See /usr/share/doc/moxi-%{version}/examples/ for configuration examples. Aborting." 30 | exit 1 31 | fi 32 | fi 33 | 34 | RETVAL=0 35 | prog="moxi" 36 | 37 | start () { 38 | echo -n $"Starting $prog: " 39 | # insure that /var/run/moxi has proper permissions 40 | chown $USER /var/run/moxi 41 | daemon /usr/bin/moxi -d -u $USER -c $MAXCONN -z $CPROXY_ARG -P /var/run/moxi/moxi.pid $OPTIONS 42 | RETVAL=$? 43 | echo 44 | [ $RETVAL -eq 0 ] && touch /var/lock/subsys/moxi 45 | } 46 | stop () { 47 | echo -n $"Stopping $prog: " 48 | killproc moxi 49 | RETVAL=$? 50 | echo 51 | if [ $RETVAL -eq 0 ] ; then 52 | rm -f /var/lock/subsys/moxi 53 | rm -f /var/run/moxi.pid 54 | fi 55 | } 56 | 57 | restart () { 58 | stop 59 | start 60 | } 61 | 62 | 63 | # See how we were called. 64 | case "$1" in 65 | start) 66 | start 67 | ;; 68 | stop) 69 | stop 70 | ;; 71 | status) 72 | status moxi 73 | ;; 74 | restart|reload) 75 | restart 76 | ;; 77 | condrestart) 78 | [ -f /var/lock/subsys/moxi ] && restart || : 79 | ;; 80 | *) 81 | echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}" 82 | exit 1 83 | esac 84 | 85 | exit $? 86 | -------------------------------------------------------------------------------- /scripts/rpm/build-fc-rpm: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf tmp/rpmbuild 4 | mkdir -p tmp/rpmbuild/SOURCES 5 | mkdir -p tmp/rpmbuild/BUILD 6 | mkdir -p tmp/rpmbuild/BUILDROOT 7 | mkdir -p tmp/rpmbuild/RPMS 8 | mkdir -p tmp/rpmbuild/SRPMS 9 | mkdir -p tmp/rpmbuild/SPECS 10 | 11 | rm -rf tmp/build 12 | mkdir tmp/build 13 | 14 | cp -R . tmp/build && \ 15 | tar cf tmp/rpmbuild/SOURCES/proxybuild.tar -C tmp proxybuild && \ 16 | rpmbuild --define="_topdir `pwd`/tmp/rpmbuild" -ba moxi.spec && \ 17 | cp tmp/rpmbuild/RPMS/*/*.rpm . 18 | -------------------------------------------------------------------------------- /src/assoc.h: -------------------------------------------------------------------------------- 1 | /* associative array */ 2 | void assoc_init(void); 3 | item *assoc_find(const char *key, const size_t nkey); 4 | int assoc_insert(item *item); 5 | void assoc_delete(const char *key, const size_t nkey); 6 | void do_assoc_move_next_bucket(void); 7 | int start_assoc_maintenance_thread(void); 8 | void stop_assoc_maintenance_thread(void); 9 | 10 | -------------------------------------------------------------------------------- /src/genhash_int.h: -------------------------------------------------------------------------------- 1 | /** 2 | * \private 3 | */ 4 | struct genhash_entry_t { 5 | /** The key for this entry */ 6 | void *key; 7 | /** The value for this entry */ 8 | void *value; 9 | /** Pointer to the next entry */ 10 | struct genhash_entry_t *next; 11 | }; 12 | 13 | struct _genhash { 14 | size_t size; 15 | struct hash_ops ops; 16 | struct genhash_entry_t *buckets[]; 17 | }; 18 | -------------------------------------------------------------------------------- /src/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 settings settings; 24 | -------------------------------------------------------------------------------- /src/hash.h: -------------------------------------------------------------------------------- 1 | #ifndef HASH_H 2 | #define HASH_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | uint32_t hash(const void *key, size_t length, const uint32_t initval); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif /* HASH_H */ 15 | 16 | -------------------------------------------------------------------------------- /src/items.h: -------------------------------------------------------------------------------- 1 | /* See items.c */ 2 | void item_init(void); 3 | uint64_t get_cas_id(void); 4 | 5 | /*@null@*/ 6 | item *do_item_alloc(char *key, const size_t nkey, const int flags, const rel_time_t exptime, const int nbytes); 7 | void item_free(item *it); 8 | bool item_size_ok(const size_t nkey, const int flags, const int nbytes); 9 | 10 | int do_item_link(item *it); /** may fail if transgresses limits */ 11 | void do_item_unlink(item *it); 12 | void do_item_remove(item *it); 13 | void do_item_update(item *it); /** update LRU time to current and reposition */ 14 | int do_item_replace(item *it, item *new_it); 15 | 16 | /*@null@*/ 17 | char *do_item_cachedump(const unsigned int slabs_clsid, const unsigned int limit, unsigned int *bytes); 18 | void do_item_stats(ADD_STAT add_stats, void *c); 19 | /*@null@*/ 20 | void do_item_stats_sizes(ADD_STAT add_stats, void *c); 21 | void do_item_flush_expired(void); 22 | 23 | item *do_item_get(const char *key, const size_t nkey); 24 | item *do_item_get_nocheck(const char *key, const size_t nkey); 25 | void item_stats_reset(void); 26 | extern cb_mutex_t cache_lock; 27 | -------------------------------------------------------------------------------- /src/log.h: -------------------------------------------------------------------------------- 1 | /* 2 | * moxi logging API 3 | * mtaneja@zynga.com 4 | */ 5 | 6 | #ifndef _LOG_H_ 7 | #define _LOG_H_ 8 | 9 | #include 10 | #include 11 | 12 | /* 13 | * define the log levels 14 | */ 15 | #define MOXI_LOG_CRIT 1 16 | #define MOXI_LOG_ERR 5 17 | #define MOXI_LOG_INFO 10 18 | #define MOXI_LOG_DEBUG 15 19 | 20 | #define ERRORLOG_STDERR 0x1 21 | #define ERRORLOG_FILE 0x2 22 | #define ERRORLOG_SYSLOG 0x4 23 | 24 | struct moxi_log { 25 | int fd; /* log fd */ 26 | int log_level; /* logging level. default 5 */ 27 | int log_mode; /* syslog, log file, stderr */ 28 | char *log_ident; /* syslog identifier */ 29 | char *log_file; /* if log file is specified */ 30 | int use_syslog; /* set if syslog is being used */ 31 | time_t base_ts; /* base timestamp */ 32 | time_t last_generated_debug_ts; 33 | }; 34 | 35 | typedef struct moxi_log moxi_log; 36 | 37 | int log_error_open(moxi_log *); 38 | int log_error_close(moxi_log *); 39 | int log_error_write(moxi_log *, const char *filename, unsigned int line, const char *fmt, ...); 40 | int log_error_cycle(moxi_log *); 41 | 42 | #ifndef MAIN_CHECK 43 | extern moxi_log *ml; 44 | #define moxi_log_write(...) log_error_write(ml, __FILE__, __LINE__, __VA_ARGS__) 45 | #else 46 | #define moxi_log_write(...) fprintf(stderr, __VA_ARGS__) 47 | #endif 48 | 49 | #undef perror 50 | #define perror(str) log_error_write(ml, __FILE__, __LINE__, str, ": %s", strerror(errno)); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/matcher.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | 3 | #ifndef MATCHER_H 4 | #define MATCHER_H 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | typedef struct { 11 | /* We have a simple implementation currently that */ 12 | /* only supports simple string prefix matching, O(N^2). */ 13 | 14 | cb_mutex_t *lock; 15 | 16 | int patterns_max; /* Size of patterns array, may be 0. */ 17 | int patterns_num; /* Number of active patterns, <= patterns_max. */ 18 | char **patterns; /* May be NULL. */ 19 | int *lengths; /* May be NULL, same size as patterns array. */ 20 | 21 | /* Statistics. */ 22 | 23 | uint64_t *hits; /* May be NULL, same size as patterns array. */ 24 | uint64_t misses; 25 | } matcher; 26 | 27 | void matcher_init(matcher *m, bool multithreaded); 28 | void matcher_start(matcher *m, char *spec); 29 | bool matcher_started(matcher *m); 30 | void matcher_stop(matcher *m); 31 | matcher *matcher_clone(matcher *m, matcher *copy); 32 | bool matcher_check(matcher *m, char *str, int str_len, 33 | bool default_when_unstarted); 34 | 35 | #endif /* MATCHER_H */ 36 | 37 | -------------------------------------------------------------------------------- /src/murmur_hash.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | /* 8 | "Murmur" hash provided by Austin, tanjent@gmail.com 9 | http://murmurhash.googlepages.com/ 10 | 11 | Note - This code makes a few assumptions about how your machine behaves - 12 | 13 | 1. We can read a 4-byte value from any address without crashing 14 | 2. sizeof(int) == 4 15 | 16 | And it has a few limitations - 17 | 1. It will not work incrementally. 18 | 2. It will not produce the same results on little-endian and big-endian 19 | machines. 20 | 21 | Updated to murmur2 hash - BP 22 | */ 23 | 24 | uint32_t murmur_hash(const char *key, size_t length); 25 | 26 | uint32_t murmur_hash(const char *key, size_t length) 27 | { 28 | /* 29 | 'm' and 'r' are mixing constants generated offline. They're not 30 | really 'magic', they just happen to work well. 31 | */ 32 | 33 | const unsigned int m= 0x5bd1e995; 34 | const unsigned int seed= (0xdeadbeef * length); 35 | const int r= 24; 36 | 37 | 38 | /* Initialize the hash to a 'random' value */ 39 | 40 | unsigned int h= seed ^ length; 41 | 42 | /* Mix 4 bytes at a time into the hash */ 43 | 44 | const unsigned char * data= (const unsigned char *)key; 45 | 46 | while(length >= 4) 47 | { 48 | unsigned int k = *(unsigned int *)data; 49 | 50 | k *= m; 51 | k ^= k >> r; 52 | k *= m; 53 | 54 | h *= m; 55 | h ^= k; 56 | 57 | data += 4; 58 | length -= 4; 59 | } 60 | 61 | /* Handle the last few bytes of the input array */ 62 | 63 | switch(length) 64 | { 65 | case 3: h ^= data[2] << 16; 66 | case 2: h ^= data[1] << 8; 67 | case 1: h ^= data[0]; 68 | h *= m; 69 | }; 70 | 71 | /* 72 | Do a few final mixes of the hash to ensure the last few bytes are 73 | well-incorporated. 74 | */ 75 | 76 | h ^= h >> 13; 77 | h *= m; 78 | h ^= h >> 15; 79 | 80 | return h; 81 | } 82 | -------------------------------------------------------------------------------- /src/redirects.c: -------------------------------------------------------------------------------- 1 | #include "redirects.h" 2 | 3 | #undef conflate_add_field 4 | #undef conflate_add_field_multi 5 | #undef conflate_next_fieldset 6 | #undef conflate_init_form 7 | 8 | void (*redirected_conflate_add_field_target)(conflate_form_result *r, const char *k, const char *v) = conflate_add_field; 9 | void (*redirected_conflate_add_field_multi_target)(conflate_form_result *r, const char *k, const char **v) = conflate_add_field_multi; 10 | void (*redirected_conflate_next_fieldset_target)(conflate_form_result *r) = conflate_next_fieldset; 11 | void (*redirected_conflate_init_form_target)(conflate_form_result *r) = conflate_init_form; 12 | 13 | 14 | #undef collect_memcached_stats_for_proxy 15 | 16 | void (*redirected_collect_memcached_stats_for_proxy_target)(struct main_stats_collect_info *msci, 17 | const char *proxy_name, 18 | int proxy_port) = collect_memcached_stats_for_proxy; 19 | void redirected_collect_memcached_stats_for_proxy(struct main_stats_collect_info *msci, 20 | const char *proxy_name, 21 | int proxy_port) 22 | { 23 | (*redirected_collect_memcached_stats_for_proxy_target)(msci, proxy_name, proxy_port); 24 | } 25 | 26 | void reset_redirections(void) 27 | { 28 | redirected_collect_memcached_stats_for_proxy_target = collect_memcached_stats_for_proxy; 29 | redirected_conflate_add_field_target = conflate_add_field; 30 | redirected_conflate_add_field_multi_target = conflate_add_field_multi; 31 | redirected_conflate_next_fieldset_target = conflate_next_fieldset; 32 | redirected_conflate_init_form_target = conflate_init_form; 33 | } 34 | 35 | void redirected_conflate_add_field(conflate_form_result *r, const char *k, const char *v) 36 | { 37 | (*redirected_conflate_add_field_target)(r,k,v); 38 | } 39 | 40 | void redirected_conflate_add_field_multi(conflate_form_result *r, const char *k, const char **v) 41 | { 42 | (*redirected_conflate_add_field_multi_target)(r,k,v); 43 | } 44 | 45 | void redirected_conflate_next_fieldset(conflate_form_result *r) 46 | { 47 | (*redirected_conflate_next_fieldset_target)(r); 48 | } 49 | 50 | void redirected_conflate_init_form(conflate_form_result *r) 51 | { 52 | (*redirected_conflate_init_form_target)(r); 53 | } 54 | -------------------------------------------------------------------------------- /src/redirects.h: -------------------------------------------------------------------------------- 1 | #ifndef REDIRECTS_H 2 | #define REDIRECTS_H 3 | #include "src/config.h" 4 | 5 | #ifdef HAVE_CONFLATE_H 6 | #include 7 | 8 | #define conflate_add_field redirected_conflate_add_field 9 | #define conflate_add_field_multi redirected_conflate_add_field_multi 10 | #define conflate_next_fieldset redirected_conflate_next_fieldset 11 | #define conflate_init_form redirected_conflate_init_form 12 | 13 | extern void (*redirected_conflate_add_field_target)(conflate_form_result *r, const char *k, const char *v); 14 | extern void (*redirected_conflate_add_field_multi_target)(conflate_form_result *r, const char *k, const char **v); 15 | extern void (*redirected_conflate_next_fieldset_target)(conflate_form_result *r); 16 | extern void (*redirected_conflate_init_form_target)(conflate_form_result *r); 17 | 18 | void redirected_conflate_add_field(conflate_form_result *r, const char *k, const char *v); 19 | void redirected_conflate_add_field_multi(conflate_form_result *r, const char *k, const char **v); 20 | void redirected_conflate_next_fieldset(conflate_form_result *r); 21 | void redirected_conflate_init_form(conflate_form_result *r); 22 | 23 | #endif /* HAVE_CONFLATE_H */ 24 | 25 | struct main_stats_collect_info; 26 | 27 | void collect_memcached_stats_for_proxy(struct main_stats_collect_info *msci, const char *proxy_name, int proxy_port); 28 | void redirected_collect_memcached_stats_for_proxy(struct main_stats_collect_info *msci, const char *proxy_name, int proxy_port); 29 | extern void (*redirected_collect_memcached_stats_for_proxy_target)(struct main_stats_collect_info *msci, const char *proxy_name, int proxy_port); 30 | 31 | #define collect_memcached_stats_for_proxy redirected_collect_memcached_stats_for_proxy 32 | 33 | void reset_redirections(void); 34 | 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/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); 12 | 13 | 14 | /** 15 | * Given object size, return id to use when allocating/freeing memory for object 16 | * 0 means error: can't store such a large object 17 | */ 18 | 19 | unsigned int slabs_clsid(const size_t size); 20 | 21 | /** Allocate object of given length. 0 on error */ /*@null@*/ 22 | void *slabs_alloc(const size_t size, unsigned int id); 23 | 24 | /** Free previously allocated object */ 25 | void slabs_free(void *ptr, size_t size, unsigned int id); 26 | 27 | /** Return a datum for stats in binary protocol */ 28 | bool get_stats(const char *stat_type, int nkey, ADD_STAT add_stats, void *c); 29 | 30 | /** Fill buffer with stats */ /*@null@*/ 31 | void slabs_stats(ADD_STAT add_stats, void *c); 32 | 33 | /* Request some slab be moved between classes 34 | 1 = success 35 | 0 = fail 36 | -1 = tried. busy. send again shortly. */ 37 | int slabs_reassign(unsigned char srcid, unsigned char dstid); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/solaris_priv.c: -------------------------------------------------------------------------------- 1 | #include "src/config.h" 2 | #include 3 | #include 4 | #include 5 | #include "memcached.h" 6 | 7 | /* 8 | * this section of code will drop all (Solaris) privileges including 9 | * those normally granted to all userland process (basic privileges). The 10 | * effect of this is that after running this code, the process will not able 11 | * to fork(), exec(), etc. See privileges(5) for more information. 12 | */ 13 | void drop_privileges(void) { 14 | priv_set_t *privs = priv_str_to_set("basic", ",", NULL); 15 | 16 | if (privs == NULL) { 17 | perror("priv_str_to_set"); 18 | exit(EXIT_FAILURE); 19 | } 20 | 21 | (void)priv_delset(privs, PRIV_FILE_LINK_ANY); 22 | (void)priv_delset(privs, PRIV_PROC_EXEC); 23 | (void)priv_delset(privs, PRIV_PROC_FORK); 24 | (void)priv_delset(privs, PRIV_PROC_INFO); 25 | (void)priv_delset(privs, PRIV_PROC_SESSION); 26 | 27 | if (setppriv(PRIV_SET, PRIV_PERMITTED, privs) != 0) { 28 | perror("setppriv(PRIV_SET, PRIV_PERMITTED)"); 29 | exit(EXIT_FAILURE); 30 | } 31 | 32 | priv_emptyset(privs); 33 | 34 | if (setppriv(PRIV_SET, PRIV_INHERITABLE, privs) != 0) { 35 | perror("setppriv(PRIV_SET, PRIV_INHERITABLE)"); 36 | exit(EXIT_FAILURE); 37 | } 38 | 39 | if (setppriv(PRIV_SET, PRIV_LIMIT, privs) != 0) { 40 | perror("setppriv(PRIV_SET, PRIV_LIMIT)"); 41 | exit(EXIT_FAILURE); 42 | } 43 | 44 | priv_freeset(privs); 45 | } 46 | -------------------------------------------------------------------------------- /src/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 | -------------------------------------------------------------------------------- /src/stdin_check.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | #include "src/config.h" 3 | #include 4 | #include 5 | 6 | #include "stdin_check.h" 7 | #include "log.h" 8 | 9 | static void check_stdin_thread(void* arg) 10 | { 11 | int ch; 12 | 13 | (void)arg; 14 | 15 | do { 16 | ch = getc(stdin); 17 | } while (ch != EOF && ch != '\n' && ch != '\r'); 18 | 19 | fprintf(stderr, "%s on stdin. Exiting\n", (ch == EOF) ? "EOF" : "EOL"); 20 | exit(0); 21 | } 22 | 23 | int stdin_check(void) { 24 | cb_thread_t t; 25 | if (cb_create_thread(&t, check_stdin_thread, NULL, 1) != 0) { 26 | perror("couldn't create stdin checking thread."); 27 | return -1; 28 | } 29 | 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /src/stdin_check.h: -------------------------------------------------------------------------------- 1 | #ifndef STDIN_CHECK_H 2 | #define STDIN_CHECK_H 3 | 4 | int stdin_check(void); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/strsep.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifdef _MSC_VER 4 | char *strsep(char **stringp, const char *pattern) { 5 | char *ptr = *stringp; 6 | 7 | char *first = NULL; 8 | int len = (int)strlen(pattern); 9 | 10 | for (int i = 0; i < len; ++i) { 11 | char *n = strchr(*stringp, pattern[i]); 12 | if (n != NULL && (first == NULL || n < first)) { 13 | first = n; 14 | } 15 | } 16 | 17 | if (first != NULL) { 18 | *first = '\0'; 19 | *stringp = first + 1; 20 | } else { 21 | *stringp = NULL; 22 | } 23 | 24 | return ptr; 25 | } 26 | #endif 27 | -------------------------------------------------------------------------------- /src/util.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef MOXI_UTIL_H 4 | #define MOXI_UTIL_H 5 | 6 | /* 7 | * Wrappers around strtoull/strtoll that are safer and easier to 8 | * use. For tests and assumptions, see internal_tests.c. 9 | * 10 | * str a NULL-terminated base decimal 10 unsigned integer 11 | * out out parameter, if conversion succeeded 12 | * 13 | * returns true if conversion succeeded. 14 | */ 15 | bool safe_strtoull(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 | 20 | /* This was stolen from the glibc docs. 21 | 22 | Why they'd write documentation to show how to do this vs. just 23 | provide the function is unclear. 24 | */ 25 | int timeval_subtract(struct timeval *result, 26 | struct timeval *x, struct timeval *y); 27 | 28 | /** 29 | * Convert a timeval to a simple double. 30 | * 31 | * This is generally useful for deltas. 32 | */ 33 | double timeval_to_double(struct timeval tv); 34 | 35 | struct moxi_stats { 36 | double min; 37 | double max; 38 | double avg; 39 | double stddev; 40 | double ninetyfifth; 41 | }; 42 | 43 | /** 44 | * Compute some statistics over a sequence. 45 | * 46 | * @param out accumulated stats for input values 47 | * @param vals input values (note: these will be reordered) 48 | * @param num_values the number of values to be processed 49 | */ 50 | void compute_stats(struct moxi_stats *out, double *vals, int num_vals); 51 | 52 | /* should be fixed in libconflate instead */ 53 | #ifdef __gcc_attribute__ 54 | #undef __gcc_attribute__ 55 | #endif 56 | 57 | #ifdef __GCC 58 | # define __gcc_attribute__ __attribute__ 59 | #else 60 | # define __gcc_attribute__(x) 61 | #endif 62 | 63 | /** 64 | * Vararg variant of perror that makes for more useful error messages 65 | * when reporting with parameters. 66 | * 67 | * @param fmt a printf format 68 | */ 69 | void vperror(const char *fmt, ...) 70 | __gcc_attribute__ ((format (printf, 1, 2))); 71 | 72 | #undef __gcc_attribute__ 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/work.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | 3 | #ifndef WORK_H 4 | #define WORK_H 5 | 6 | #include "src/config.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | typedef struct work_item work_item; 15 | typedef struct work_queue work_queue; 16 | typedef struct work_collect work_collect; 17 | 18 | struct work_item { 19 | void (*func)(void *data0, void *data1); 20 | void *data0; 21 | void *data1; 22 | work_item *next; 23 | }; 24 | 25 | struct work_queue { 26 | SOCKET send_fd; /* Pipe to notify thread. */ 27 | SOCKET recv_fd; 28 | 29 | work_item *work_head; 30 | work_item *work_tail; 31 | 32 | uint64_t num_items; /* Current number of items in queue. */ 33 | uint64_t tot_sends; 34 | uint64_t tot_recvs; 35 | 36 | struct event_base *event_base; 37 | struct event event; 38 | 39 | cb_mutex_t work_lock; 40 | }; 41 | 42 | struct work_collect { 43 | int count; 44 | 45 | void *data; 46 | 47 | cb_mutex_t collect_lock; 48 | cb_cond_t collect_cond; /* Signaled when count drops to 0. */ 49 | }; 50 | 51 | bool work_queue_init(work_queue *m, struct event_base *base); 52 | 53 | bool work_send(work_queue *m, 54 | void (*func)(void *data0, void *data1), 55 | void *data0, void *data1); 56 | 57 | void work_recv(evutil_socket_t fd, short which, void *arg); 58 | 59 | int work_collect_init(work_collect *c, int count, void *data); 60 | int work_collect_wait(work_collect *c); 61 | int work_collect_count(work_collect *c, int count); 62 | int work_collect_one(work_collect *c); 63 | 64 | #endif /* WORK_H */ 65 | -------------------------------------------------------------------------------- /t/00-startup.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 17; 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 1'); 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 | -------------------------------------------------------------------------------- /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 1 6\r\nfooval\r\n"; 32 | is(scalar <$sock>, "STORED\r\n", "stored foo"); 33 | 34 | mem_get_is($sock, "foo", "fooval"); 35 | sleep(1.5); 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 | -------------------------------------------------------------------------------- /t/flags.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 | # set foo (and should get it) 13 | for my $flags (0, 123, 2**16-1) { 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 | -------------------------------------------------------------------------------- /t/flush-all.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 14; 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(2.2); 44 | mem_get_is($sock, "foo", undef); 45 | -------------------------------------------------------------------------------- /t/incrdecr.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More tests => 22; 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 | 20 | # SKIP this test for moxi... 21 | # print $sock "decr bug21 1\r\n"; 22 | # is(scalar <$sock>, "9223372036854775808\r\n", "bug21 decr"); 23 | 24 | print $sock "set num 0 0 1\r\n1\r\n"; 25 | is(scalar <$sock>, "STORED\r\n", "stored num"); 26 | mem_get_is($sock, "num", 1, "stored 1"); 27 | 28 | print $sock "incr num 1\r\n"; 29 | is(scalar <$sock>, "2\r\n", "+ 1 = 2"); 30 | mem_get_is($sock, "num", 2); 31 | 32 | print $sock "incr num 8\r\n"; 33 | is(scalar <$sock>, "10\r\n", "+ 8 = 10"); 34 | mem_get_is($sock, "num", 10); 35 | 36 | print $sock "decr num 1\r\n"; 37 | is(scalar <$sock>, "9\r\n", "- 1 = 9"); 38 | 39 | print $sock "decr num 9\r\n"; 40 | is(scalar <$sock>, "0\r\n", "- 9 = 0"); 41 | 42 | print $sock "decr num 5\r\n"; 43 | is(scalar <$sock>, "0\r\n", "- 5 = 0"); 44 | 45 | printf $sock "set num 0 0 10\r\n4294967296\r\n"; 46 | is(scalar <$sock>, "STORED\r\n", "stored 2**32"); 47 | 48 | print $sock "incr num 1\r\n"; 49 | is(scalar <$sock>, "4294967297\r\n", "4294967296 + 1 = 4294967297"); 50 | 51 | printf $sock "set num 0 0 %d\r\n18446744073709551615\r\n", length("18446744073709551615"); 52 | is(scalar <$sock>, "STORED\r\n", "stored 2**64-1"); 53 | 54 | print $sock "incr num 1\r\n"; 55 | is(scalar <$sock>, "0\r\n", "(2**64 - 1) + 1 = 0"); 56 | 57 | print $sock "decr bogus 5\r\n"; 58 | is(scalar <$sock>, "NOT_FOUND\r\n", "can't decr bogus key"); 59 | 60 | print $sock "decr incr 5\r\n"; 61 | is(scalar <$sock>, "NOT_FOUND\r\n", "can't incr bogus key"); 62 | 63 | print $sock "set bigincr 0 0 1\r\n0\r\n"; 64 | is(scalar <$sock>, "STORED\r\n", "stored bigincr"); 65 | print $sock "incr bigincr 18446744073709551610\r\n"; 66 | is(scalar <$sock>, "18446744073709551610\r\n"); 67 | 68 | print $sock "set text 0 0 2\r\nhi\r\n"; 69 | is(scalar <$sock>, "STORED\r\n", "stored hi"); 70 | print $sock "incr text 1\r\n"; 71 | is(scalar <$sock>, 72 | "CLIENT_ERROR cannot increment or decrement non-numeric value\r\n", 73 | "hi - 1 = 0"); 74 | -------------------------------------------------------------------------------- /t/issue-MB-2649.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ret=0 4 | 5 | if [ ! -f ../labrea/labrea ] ; then 6 | echo SKIPPED - require labrea 7 | exit 0 8 | fi 9 | 10 | killall moxi || true 11 | 12 | echo " 13 | -- Slow down reads 14 | function before_read(...) 15 | labrea.usleep(200000) 16 | end 17 | " > /tmp/slow-node.lua 18 | 19 | echo starting slow memcached simulant 11277 20 | 21 | ../labrea/labrea /tmp/slow-node.lua \ 22 | ./moxi -d -P /tmp/moxi-slow-node-test-memcached0.pid -p 11277 23 | 24 | sleep 1 25 | 26 | echo -e "set a 0 0 1\r\na\r" | nc 127.0.0.1 11277 27 | 28 | echo starting moxi... 29 | 30 | ./moxi -d -P /tmp/moxi-slow-node-test-moxi.pid \ 31 | -z 11266=127.0.0.1:11277 -t 1 \ 32 | -Z downstream_conn_max=1,downstream_max=0,downstream_conn_queue_timeout=100,wait_queue_timeout=0 33 | 34 | sleep 1 35 | 36 | echo 1 request to take up the 1 downstream conn 37 | echo get a | nc 127.0.0.1 11266 > /tmp/slow-node-0.out & 38 | 39 | echo expect timeout on next requests 40 | echo get a | nc 127.0.0.1 11266 > /tmp/slow-node-1.out & 41 | 42 | echo expect timeout on next requests 43 | echo get a | nc 127.0.0.1 11266 > /tmp/slow-node-2.out & 44 | 45 | sleep 1 46 | 47 | count=$(grep "VALUE" /tmp/slow-node-0.out | wc -l) 48 | if [[ $count -ne 1 ]] ; then 49 | echo "FAIL expected VALUE" 50 | ret=1 51 | else 52 | echo "OK expected VALUE" 53 | fi 54 | 55 | count=$(grep "VALUE" /tmp/slow-node-1.out | wc -l) 56 | if [[ $count -ne 0 ]] ; then 57 | echo "FAIL expected no VALUE" 58 | ret=1 59 | else 60 | echo "OK expected no VALUE" 61 | fi 62 | 63 | count=$(grep "VALUE" /tmp/slow-node-2.out | wc -l) 64 | if [[ $count -ne 0 ]] ; then 65 | echo "FAIL expected no VALUE" 66 | ret=1 67 | else 68 | echo "OK expected no VALUE" 69 | fi 70 | 71 | sleep 1 72 | 73 | count=$(echo get a | nc 127.0.0.1 11266 | grep "VALUE" | wc -l) 74 | if [[ $count -ne 1 ]] ; then 75 | echo "FAIL expected VALUE" 76 | ret=1 77 | else 78 | echo "OK expected VALUE after downstream_conn_queue timeouts" 79 | fi 80 | 81 | killall moxi 82 | 83 | exit $ret 84 | -------------------------------------------------------------------------------- /t/issue-MB-2660.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo starting moxi... 4 | 5 | # Note that changing downstream_conn_max to 0 (correctly) does not hang. 6 | 7 | ./moxi -d -P /tmp/moxi-dcm-test-moxi.pid \ 8 | -z 11266=127.0.0.1:11277 \ 9 | -Z downstream_conn_max=1,downstream_max=0,downstream_timeout=5000,wait_queue_timeout=5000,downstream_retry=1 -t 1 10 | 11 | echo starting memcached simulant... 12 | 13 | ./moxi -d -P /tmp/moxi-dcm-test-memcached.pid -p 11277 14 | 15 | echo client request 1 - expect NOT_FOUND 16 | 17 | time (echo incr a 1 | nc 127.0.0.1 11266) 18 | 19 | echo killing memcached simulant... 20 | 21 | kill `cat /tmp/moxi-dcm-test-memcached.pid` 22 | 23 | echo client request 2 - hangs in bug MB-2660, instead expect SERVER_ERROR 24 | 25 | time (echo incr a 1 | nc 127.0.0.1 11266) 26 | 27 | echo client request 3 - hangs in one fix attempt, instead expect SERVER_ERROR 28 | 29 | time (echo incr a 1 | nc 127.0.0.1 11266) 30 | 31 | echo client request 4 - expect SERVER_ERROR 32 | 33 | time (echo incr a 1 | nc 127.0.0.1 11266) 34 | 35 | echo OK - no more hanging 36 | 37 | killall moxi 38 | 39 | -------------------------------------------------------------------------------- /t/issue-MB-2689.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo starting moxi... 4 | 5 | # Note, if you removed or zero'ed the timeouts, moxi would also 6 | # (correctly, expectedly) hang at client request 2. 7 | 8 | ./moxi -d -P /tmp/moxi-2689-test-moxi.pid \ 9 | -z 11266=127.0.0.1:11277 -t 1 \ 10 | -Z downstream_conn_max=1,downstream_max=0,downstream_timeout=100,wait_queue_timeout=100 11 | 12 | echo starting memcached simulant... 13 | 14 | ./moxi -d -P /tmp/moxi-2689-test-memcached.pid -p 11277 15 | 16 | echo client request 1 - expect NOT_FOUND 17 | time (echo incr a 1 | nc 127.0.0.1 11266) 18 | 19 | echo stopping memcached simulant... 20 | kill -STOP `cat /tmp/moxi-2689-test-memcached.pid` 21 | 22 | echo client request 2 - hangs in bug MB-2689, instead expect SERVER_ERROR 23 | time (echo incr a 1 | nc 127.0.0.1 11266) 24 | 25 | echo client request 3 - expect SERVER_ERROR 26 | time (echo incr a 1 | nc 127.0.0.1 11266) 27 | 28 | echo client request 4 - expect SERVER_ERROR 29 | time (echo incr a 1 | nc 127.0.0.1 11266) 30 | 31 | echo OK - no more hanging 32 | killall moxi 33 | 34 | -------------------------------------------------------------------------------- /t/issue-MB-2825.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo starting moxi... 4 | 5 | # Note, if you zero'ed the timeouts, moxi would also 6 | # (unsurprisingly) hang at client request 3. 7 | 8 | ./moxi -d -P /tmp/moxi-2825-test-moxi.pid \ 9 | -z 11266=127.0.0.1:11277 -t 1 \ 10 | -Z downstream_conn_max=1,downstream_max=0,downstream_timeout=0,wait_queue_timeout=0,downstream_conn_queue_timeout=100 11 | 12 | echo starting memcached simulant... 13 | 14 | ./moxi -d -P /tmp/moxi-2825-test-memcached.pid -p 11277 15 | 16 | echo client request 1 - expect NOT_FOUND 17 | time (echo incr a 1 | nc 127.0.0.1 11266) 18 | 19 | echo stopping memcached simulant... 20 | kill -STOP `cat /tmp/moxi-2825-test-memcached.pid` 21 | 22 | echo client request 2 - use up the one downstream conn 23 | time (echo incr a 2 | nc 127.0.0.1 11266) & 24 | 25 | sleep 1 26 | 27 | echo client request 3 - hangs in 2825, with the fix expect SERVER_ERROR 28 | time (echo incr a 3 | nc 127.0.0.1 11266) 29 | 30 | echo client request 4 - hangs in 2825, with the fix expect SERVER_ERROR 31 | time (echo incr a 4 | nc 127.0.0.1 11266) 32 | 33 | echo OK - no more hanging 34 | killall moxi 35 | 36 | -------------------------------------------------------------------------------- /t/issue-MB-3113.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ret=0 4 | 5 | echo starting saslBucketsStreamingSimulant... 6 | 7 | ( cat << EOF 8 | HTTP/1.0 200 OK 9 | 10 | {"buckets":[]} 11 | 12 | 13 | 14 | 15 | EOF 16 | ) | nc -l 22100 & 17 | 18 | echo starting moxi... 19 | 20 | ./moxi -d -P /tmp/moxi-3113-test-moxi.pid \ 21 | -z http://127.0.0.1:22100/saslBucketsStreamingSimulant -t 1 \ 22 | -Z default_bucket_name=default,port_listen=11266 23 | 24 | sleep 3 25 | 26 | # Before the fix, these requests would incorrectly return... 27 | # 28 | # SERVER_ERROR unauthorized, null bucket 29 | # 30 | # Instead, we want moxi to just close the upstream conn 31 | # when there are no buckets, so that upstream conn's are 32 | # not inadvertently stuck on null bucket. 33 | # 34 | echo -e "incr a 1\r\nincr a 2\r" | nc 127.0.0.1 11266 35 | 36 | count=$(echo -e "incr a 1\r\nincr a 2\r" | nc 127.0.0.1 11266 | wc -l) 37 | if [[ $count -ne 0 ]] ; then 38 | echo "FAIL expected closed conns (especially not '')" 39 | ret=1 40 | else 41 | echo "OK got closed conns" 42 | fi 43 | 44 | killall moxi 45 | 46 | exit $ret 47 | -------------------------------------------------------------------------------- /t/issue-conn-close.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo starting moxi... 4 | 5 | ./moxi -d -P /tmp/moxi-conn-close-moxi.pid \ 6 | -z 11266=127.0.0.1:11277 -t 1 \ 7 | -Z downstream_conn_max=1,downstream_max=0,downstream_timeout=0,wait_queue_timeout=0,downstream_conn_queue_timeout=100,retry=0 8 | 9 | echo starting memcached simulant... 10 | ./moxi -d -P /tmp/moxi-conn-close-memcached.pid -p 11277 11 | sleep 2; 12 | 13 | echo client request 1 - expect NOT_FOUND 14 | echo incr a 1 | nc 127.0.0.1 11266 15 | 16 | echo stopping memcached simulant... 17 | kill -9 `cat /tmp/moxi-conn-close-memcached.pid` 18 | 19 | echo starting again memcached simulant... 20 | ./moxi -d -p 11277 21 | sleep 2 22 | 23 | echo client request 2 - use up the one downstream conn. since that downstream connection is closed, \ 24 | and retry is zero, in the old moxi, it should have returned the downstream close error. But with the conn-close fix \ 25 | response will be NOT_FOUND. 26 | out=`echo incr a 2 | nc 127.0.0.1 11266` 27 | 28 | if [[ "$out" != NOT_FOUND* ]];then 29 | echo "Test case failed" 30 | else 31 | echo "Test case passed" 32 | fi 33 | 34 | echo stopping moxi... 35 | killall moxi 36 | 37 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 ("0", $second_evicted, "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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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(); 10 | my $sock = $server->sock; 11 | my $value = "B"x10; 12 | my $key = 0; 13 | 14 | for ($key = 0; $key < 10; $key++) { 15 | print $sock "set key$key 0 0 10\r\n$value\r\n"; 16 | is (scalar <$sock>, "STORED\r\n", "stored key$key"); 17 | } 18 | 19 | my $first_stats = mem_stats($sock, "slabs"); 20 | my $req = $first_stats->{"1:mem_requested"}; 21 | ok ($req == "640" || $req == "800", "Check allocated size"); 22 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /t/ketama_rest_mixed.cfg: -------------------------------------------------------------------------------- 1 | { "buckets": [ 2 | { "name": "default", 3 | "nodes":[{"hostname":"127.0.0.1", 4 | "version":"unknown", 5 | "os":"unknown", 6 | "ports":{"proxy":11213,"direct":11212}, 7 | "uptime":"0", 8 | "memoryTotal":0, 9 | "memoryFree":0, 10 | "mcdMemoryReserved":64, 11 | "mcdMemoryAllocated":0}], 12 | "nodeLocator": "vbucket", 13 | "vBucketServerMap": { 14 | "hashAlgorithm": "CRC", 15 | "numReplicas": 0, 16 | "user": "default", 17 | "password": "", 18 | "serverList": ["127.0.0.1:11311"], 19 | "vBucketMap": 20 | [ [0] ] 21 | } 22 | }, 23 | { "name": "k", 24 | "nodes":[{"hostname":"127.0.0.1", 25 | "version":"unknown", 26 | "os":"unknown", 27 | "ports":{"proxy":11213,"direct":11212}, 28 | "uptime":"0", 29 | "memoryTotal":0, 30 | "memoryFree":0, 31 | "mcdMemoryReserved":64, 32 | "mcdMemoryAllocated":0}], 33 | "nodeLocator": "ketama", 34 | "vBucketServerMap": { 35 | "hashAlgorithm": "CRC", 36 | "numReplicas": 0, 37 | "user": "k", 38 | "password": "passwordGood_k", 39 | "serverList": ["127.0.0.1:11311"], 40 | "vBucketMap": 41 | [ ] 42 | } 43 | }, 44 | { "name": "v", 45 | "nodes":[{"hostname":"127.0.0.1", 46 | "version":"unknown", 47 | "os":"unknown", 48 | "ports":{"proxy":11213,"direct":11212}, 49 | "uptime":"0", 50 | "memoryTotal":0, 51 | "memoryFree":0, 52 | "mcdMemoryReserved":64, 53 | "mcdMemoryAllocated":0}], 54 | "nodeLocator": "vbucket", 55 | "vBucketServerMap": { 56 | "hashAlgorithm": "CRC", 57 | "numReplicas": 0, 58 | "user": "v", 59 | "password": "passwordGood_v", 60 | "serverList": ["127.0.0.1:11311"], 61 | "vBucketMap": 62 | [ [0] ] 63 | } 64 | } 65 | ]} 66 | -------------------------------------------------------------------------------- /t/ketama_rest_one.cfg: -------------------------------------------------------------------------------- 1 | {"name":"default", 2 | "nodeLocator":"ketama", 3 | "bucketType":"membase", 4 | "authType":"sasl", 5 | "saslPassword":"", 6 | "nodes":[{"hostname":"127.0.0.1", 7 | "version":"unknown", 8 | "os":"unknown", 9 | "ports":{"proxy":11213,"direct":11212}, 10 | "uptime":"0", 11 | "memoryTotal":0, 12 | "memoryFree":0, 13 | "mcdMemoryReserved":64, 14 | "mcdMemoryAllocated":0}], 15 | "there_is_no_vBucketServerMap":{ 16 | "hashAlgorithm":"CRC", 17 | "numReplicas":0, 18 | "serverList":["127.0.0.1:11212"], 19 | "vBucketMap":[[0],[0]]}} -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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(); 11 | my $sock = $server->sock; 12 | 13 | # create a big value for the largest slab 14 | my $max = 1024 * 1024; 15 | my $big = "a big value that's > .5M and < 1M. "; 16 | while (length($big) * 2 < $max) { 17 | $big = $big . $big; 18 | } 19 | 20 | ok(length($big) > 512 * 1024); 21 | ok(length($big) < 1024 * 1024); 22 | 23 | # test that an even bigger value is rejected while we're here 24 | my $too_big = $big . $big . $big; 25 | my $len = length($too_big); 26 | print $sock "set too_big 0 0 $len\r\n$too_big\r\n"; 27 | is(scalar <$sock>, "SERVER_ERROR object too large for cache\r\n", "too_big not stored"); 28 | 29 | # set the big value 30 | my $len = length($big); 31 | print $sock "set big 0 0 $len\r\n$big\r\n"; 32 | is(scalar <$sock>, "STORED\r\n", "stored big"); 33 | mem_get_is($sock, "big", $big); 34 | 35 | # no evictions yet 36 | my $stats = mem_stats($sock); 37 | is($stats->{"evictions"}, "0", "no evictions to start"); 38 | 39 | # set many big items, enough to get evictions 40 | for (my $i = 0; $i < 100; $i++) { 41 | print $sock "set item_$i 0 0 $len\r\n$big\r\n"; 42 | is(scalar <$sock>, "STORED\r\n", "stored item_$i"); 43 | } 44 | 45 | # some evictions should have happened 46 | my $stats = mem_stats($sock); 47 | my $evictions = int($stats->{"evictions"}); 48 | ok($evictions == 37, "some evictions happened"); 49 | 50 | # the first big value should be gone 51 | mem_get_is($sock, "big", undef); 52 | 53 | # the earliest items should be gone too 54 | for (my $i = 0; $i < $evictions - 1; $i++) { 55 | mem_get_is($sock, "item_$i", undef); 56 | } 57 | 58 | # check that the non-evicted are the right ones 59 | for (my $i = $evictions - 1; $i < $evictions + 4; $i++) { 60 | mem_get_is($sock, "item_$i", $big); 61 | } 62 | -------------------------------------------------------------------------------- /t/maxconns.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 | 13 | # start up a server with 10 maximum connections 14 | my $server = new_memcached('-c 10'); 15 | my $sock = $server->sock; 16 | my @sockets; 17 | 18 | ok(defined($sock), 'Connection 0'); 19 | push (@sockets, $sock); 20 | 21 | 22 | foreach my $conn (1..10) { 23 | $sock = $server->new_sock; 24 | ok(defined($sock), "Made connection $conn"); 25 | push(@sockets, $sock); 26 | } 27 | -------------------------------------------------------------------------------- /t/moxi_mock.cfg: -------------------------------------------------------------------------------- 1 | 11333 = { 2 | "hashAlgorithm": "CRC", 3 | "numReplicas": 0, 4 | "serverList": ["127.0.0.1:11311"], 5 | "vBucketMap": 6 | [ 7 | [0] 8 | ] 9 | } 10 | -------------------------------------------------------------------------------- /t/moxi_multitenancy_rest.cfg: -------------------------------------------------------------------------------- 1 | { "buckets": [ 2 | { "name": "bucket0", 3 | "saslPassword": "passwordGood0", 4 | "vBucketServerMap": { 5 | "hashAlgorithm": "CRC", 6 | "numReplicas": 0, 7 | "serverList": ["127.0.0.1:11311"], 8 | "vBucketMap": 9 | [ [0] ] 10 | } 11 | }, 12 | { "name": "bucket1", 13 | "saslPassword": "passwordGood1", 14 | "vBucketServerMap": { 15 | "hashAlgorithm": "CRC", 16 | "numReplicas": 0, 17 | "serverList": ["127.0.0.1:11311"], 18 | "vBucketMap": 19 | [ [0] ] 20 | } 21 | } 22 | ]} 23 | -------------------------------------------------------------------------------- /t/moxi_multitenancy_rest_default.cfg: -------------------------------------------------------------------------------- 1 | { "buckets": [ 2 | { "name": "default", 3 | "saslPassword": "", 4 | "vBucketServerMap": { 5 | "hashAlgorithm": "CRC", 6 | "numReplicas": 0, 7 | "serverList": ["127.0.0.1:11311"], 8 | "vBucketMap": 9 | [ [0] ] 10 | } 11 | }, 12 | { "name": "bucket0", 13 | "saslPassword": "passwordGood0", 14 | "vBucketServerMap": { 15 | "hashAlgorithm": "CRC", 16 | "numReplicas": 0, 17 | "serverList": ["127.0.0.1:11311"], 18 | "vBucketMap": 19 | [ [0] ] 20 | } 21 | }, 22 | { "name": "bucket1", 23 | "saslPassword": "passwordGood1", 24 | "vBucketServerMap": { 25 | "hashAlgorithm": "CRC", 26 | "numReplicas": 0, 27 | "serverList": ["127.0.0.1:11311"], 28 | "vBucketMap": 29 | [ [0] ] 30 | } 31 | } 32 | ]} 33 | -------------------------------------------------------------------------------- /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 | is(read($sock, $buf, $size / 2), $size / 2, "read half the answer back"); 28 | like($buf, qr/VALUE big/, "buf has big value header in it"); 29 | like($buf, qr/abcdef/, "buf has some data in it"); 30 | unlike($buf, qr/abcde\]/, "buf doesn't yet close"); 31 | 32 | # sock2 interrupts (maybe sock1 is slow) and deletes stuff: 33 | print $sock2 "delete big\r\n"; 34 | is(scalar <$sock2>, "DELETED\r\n", "deleted big from sock2 while sock1's still reading it"); 35 | mem_get_is($sock2, "big", undef, "nothing from sock2 now. gone from namespace."); 36 | print $sock2 "set big 0 0 $size\r\n$bigval2\r\n"; 37 | is(scalar <$sock2>, "STORED\r\n", "stored big w/ val2"); 38 | mem_get_is($sock2, "big", $bigval2, "big value2 got correctly"); 39 | 40 | # sock1 resumes reading... 41 | $buf .= <$sock>; 42 | $buf .= <$sock>; 43 | like($buf, qr/abcde\]/, "buf now closes"); 44 | 45 | # and if sock1 reads again, it's the uppercase version: 46 | mem_get_is($sock, "big", $bigval2, "big value2 got correctly from sock1"); 47 | -------------------------------------------------------------------------------- /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 | 48 | -------------------------------------------------------------------------------- /t/rest_mock.rb: -------------------------------------------------------------------------------- 1 | # This is a fake http/REST server. 2 | # 3 | # ruby ./t/cluster_manager_mock.rb [optional_path_to_some_json_contents] 4 | # 5 | # For example... 6 | # 7 | # ruby ./t/cluster_manager_mock.rb ./t/vbucket1.cfg 8 | # 9 | require 'rubygems' 10 | require 'sinatra' 11 | 12 | get '/pools/default/buckets/default' do 13 | some_json 14 | end 15 | 16 | get '/pools/default/bucketsStreaming/default' do 17 | some_json + "\n\n\n\n" 18 | end 19 | 20 | get '/pools/default/bucketsStreamingConfig/default' do 21 | some_json + "\n\n\n\n" 22 | end 23 | 24 | def some_json() 25 | if ARGV.length > 0 26 | return File.read(ARGV[0]) 27 | end 28 | 29 | <<-eos 30 | { 31 | "name": "TheUser", 32 | "saslPassword": "ThePassword", 33 | "vBucketServerMap": { 34 | "hashAlgorithm": "CRC", 35 | "numReplicas": 0, 36 | "serverList": ["127.0.0.1:11311"], 37 | "vBucketMap": 38 | [ 39 | [0] 40 | ] 41 | } 42 | } 43 | eos 44 | end 45 | 46 | -------------------------------------------------------------------------------- /t/slab-reassign.t: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | use strict; 4 | use Test::More skip_all => "Tests not written."; # 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 | -------------------------------------------------------------------------------- /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 0\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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /t/vbucket1.cfg: -------------------------------------------------------------------------------- 1 | 11211 = { 2 | "hashAlgorithm": "CRC", 3 | "numReplicas": 0, 4 | "serverList": ["localhost:11311"], 5 | "vBucketMap": 6 | [ 7 | [0], 8 | [0], 9 | [0], 10 | [0] 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /t/vbucket2.cfg: -------------------------------------------------------------------------------- 1 | 11211 = { 2 | "hashAlgorithm": "CRC", 3 | "numReplicas": 1, 4 | "serverList": ["localhost:11311", "localhost:11312"], 5 | "vBucketMap": 6 | [ 7 | [0, 1], 8 | [1, 0] 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /t/vbucket_rest1.cfg: -------------------------------------------------------------------------------- 1 | { 2 | "vBucketServerMap": { 3 | "hashAlgorithm": "CRC", 4 | "numReplicas": 1, 5 | "serverList": ["localhost:11311", "localhost:11312"], 6 | "vBucketMap": 7 | [ 8 | [0, 1], 9 | [1, 0] 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /t/vbucket_rest2.cfg: -------------------------------------------------------------------------------- 1 | {"name":"default","uri":"/pools/default/buckets/default","streamingUri":"/pools/default/bucketsStreaming/default","flushCacheUri":"/pools/default/buckets/default/controller/doFlush","nodes":[{"clusterMembership":"inactiveAdded","status":"unhealthy","hostname":"127.0.0.1","version":"unknown","os":"unknown","ports":{"proxy":11213,"direct":11212},"uptime":"0","memoryTotal":0,"memoryFree":0,"mcdMemoryReserved":64,"mcdMemoryAllocated":0}],"stats":{"uri":"/pools/default/buckets/default/stats"},"vBucketServerMap":{"hashAlgorithm":"CRC","numReplicas":0,"serverList":["127.0.0.1:11212"],"vBucketMap":[[0],[0]]},"basicStats":{"cacheSize":64,"opsPerSec":0.0,"evictionsPerSec":0.0,"cachePercentUsed":0.0}} 2 | -------------------------------------------------------------------------------- /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 | @files = grep {! /^config.h$/ } (glob("*.h"), glob("*.c"), glob("*.ac"), 9 | "memcached.spec.in"); 10 | } 11 | use Test::More tests => scalar(@files); 12 | 13 | foreach my $f (@files) { 14 | open(my $fh, $f) or die "Cannot open $f: $!"; 15 | my $before = do { local $/; <$fh>; }; 16 | close ($fh); 17 | my $after = $before; 18 | $after =~ s/\t/ /g; 19 | $after =~ s/ +$//mg; 20 | $after .= "\n" unless $after =~ /\n$/; 21 | ok ($after eq $before, "$f (see devtools/clean-whitespace.pl)"); 22 | } 23 | -------------------------------------------------------------------------------- /tests/conflate/test_common.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "test_common.h" 6 | 7 | void fail_if_impl(bool val, const char *msg, const char *file, int line) { 8 | if (val) { 9 | fprintf(stderr, "%s at %s:%d\n", msg, file, line); 10 | exit(1); 11 | } 12 | } 13 | 14 | void check_pair_equality(kvpair_t *one, kvpair_t *two) 15 | { 16 | int i = 0; 17 | fail_if(one == NULL, "one is null."); 18 | fail_if(one == two, "Comparing identical pairs."); 19 | fail_unless(strcmp(one->key, two->key) == 0, "Keys don't match."); 20 | 21 | for (i=0; one->values[i]; i++) { 22 | fail_unless(two->values[i] != NULL, "Value at one, but not two"); 23 | fail_unless(strcmp(one->values[i], two->values[i]) == 0, 24 | "Values don't match."); 25 | fail_unless((one->values[i+1] != NULL && two->values[i+1] != NULL) 26 | || (one->values[i+1] == NULL && two->values[i+1] == NULL), 27 | "Unbalanced values."); 28 | 29 | } 30 | 31 | if (one->next) { 32 | fail_unless(two->next != NULL, "No two->next."); 33 | check_pair_equality(one->next, two->next); 34 | } else { 35 | fail_if(two->next, "No one->next, but a two->next"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tests/conflate/test_common.h: -------------------------------------------------------------------------------- 1 | #ifndef TEST_COMMON_H 2 | #define TEST_COMMON_H 1 3 | 4 | #include 5 | 6 | void fail_if_impl(bool val, const char *msg, const char *file, int line); 7 | 8 | 9 | #define fail_if(a, b) fail_if_impl(a, b, __FILE__, __LINE__) 10 | #define fail_unless(a, b) fail_if(!(a), b) 11 | 12 | void check_pair_equality(kvpair_t *one, kvpair_t *two); 13 | 14 | #endif /* TEST_COMMMON_H */ 15 | -------------------------------------------------------------------------------- /tests/moxi/sizes.c: -------------------------------------------------------------------------------- 1 | #include "src/config.h" 2 | #include 3 | 4 | #include "src/memcached.h" 5 | 6 | static void display(const char *name, size_t size) { 7 | printf("%s\t%d\n", name, (int)size); 8 | } 9 | 10 | int main(void) { 11 | 12 | display("Slab Stats", sizeof(struct slab_stats)); 13 | display("Thread stats", 14 | sizeof(struct thread_stats) 15 | - (200 * sizeof(struct slab_stats))); 16 | display("Global stats", sizeof(struct stats)); 17 | display("Settings", sizeof(struct settings)); 18 | display("Item (no cas)", sizeof(item)); 19 | display("Item (cas)", sizeof(item) + sizeof(uint64_t)); 20 | display("Libevent thread", 21 | sizeof(LIBEVENT_THREAD) - sizeof(struct thread_stats)); 22 | display("Connection", sizeof(conn)); 23 | 24 | printf("----------------------------------------\n"); 25 | 26 | display("libevent thread cumulative", sizeof(LIBEVENT_THREAD)); 27 | display("Thread stats cumulative\t", sizeof(struct thread_stats)); 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /tests/vbucket/config/ketama-eight-nodes.md5sum: -------------------------------------------------------------------------------- 1 | 7f4da8f120e89d695094f45a74346dbe 2 | -------------------------------------------------------------------------------- /tests/vbucket/config/ketama-ordered-eight-nodes.md5sum: -------------------------------------------------------------------------------- 1 | 7f4da8f120e89d695094f45a74346dbe 2 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config: -------------------------------------------------------------------------------- 1 | { 2 | "hashAlgorithm": "CRC", 3 | "numReplicas": 2, 4 | "serverList": [ 5 | "server1:11211", 6 | "server2:11210", 7 | "server3:11211" 8 | ], 9 | "vBucketMap": [ 10 | [ 0, 1, 2 ], 11 | [ 1, 2, 0 ], 12 | [ 2, 1, -1 ], 13 | [ 1, 2, 0 ] 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config-couch-api-base: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": [ 3 | { 4 | "hostname": "192.168.2.123:9002", 5 | "couchApiBase": "http://192.168.2.123:9502/default", 6 | "ports": { 7 | "proxy": 12005, 8 | "direct": 12004 9 | } 10 | }, 11 | { 12 | "hostname": "192.168.2.123:9000", 13 | "couchApiBase": "http://192.168.2.123:9500/default", 14 | "ports": { 15 | "proxy": 12001, 16 | "direct": 12000 17 | } 18 | }, 19 | { 20 | "hostname": "192.168.2.123:9001", 21 | "couchApiBase": "http://192.168.2.123:9501/default", 22 | "ports": { 23 | "proxy": 12003, 24 | "direct": 12002 25 | } 26 | } 27 | ], 28 | "vBucketServerMap": { 29 | "hashAlgorithm": "CRC", 30 | "numReplicas": 1, 31 | "serverList": [ 32 | "192.168.2.123:12000", 33 | "192.168.2.123:12002", 34 | "192.168.2.123:12004" 35 | ], 36 | "vBucketMap": [ 37 | [ 0, 1 ], 38 | [ 0, 1 ], 39 | [ 0, 1 ], 40 | [ 1, 2 ], 41 | [ 1, 2 ], 42 | [ 2, 0 ], 43 | [ 2, 1 ], 44 | [ 2, 1 ], 45 | [ 1, 0 ], 46 | [ 1, 0 ], 47 | [ 1, 0 ], 48 | [ 0, 2 ], 49 | [ 0, 2 ], 50 | [ 0, 2 ], 51 | [ 2, 0 ], 52 | [ 2, 0 ] 53 | ] 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config-diff1: -------------------------------------------------------------------------------- 1 | { 2 | "hashAlgorithm": "CRC", 3 | "numReplicas": 2, 4 | "serverList": [ 5 | "server1:11211", 6 | "server2:11210", 7 | "server3:11211" 8 | ], 9 | "vBucketMap": [ 10 | [ 0, 1, 2 ], 11 | [ 1, 2, 0 ], 12 | [ 2, 1, -1 ], 13 | [ 1, 2, 0 ] 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config-diff2: -------------------------------------------------------------------------------- 1 | { 2 | "hashAlgorithm": "CRC", 3 | "numReplicas": 2, 4 | "serverList": [ 5 | "server1:11211", 6 | "server2:11210", 7 | "server4:11211" 8 | ], 9 | "vBucketMap": [ 10 | [ 0, 1, 2 ], 11 | [ 1, 2, 0 ], 12 | [ 2, 1, -1 ], 13 | [ 0, 2, 0 ] 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config-diff3: -------------------------------------------------------------------------------- 1 | { 2 | "hashAlgorithm": "CRC", 3 | "numReplicas": 1, 4 | "serverList": [ 5 | "server1:11211", 6 | "server2:11210" 7 | ], 8 | "vBucketMap": [ 9 | [ 0, 1 ], 10 | [ 1, 0 ], 11 | [ 1, 0 ], 12 | [ 0, 1 ], 13 | [ 0, 1 ], 14 | [ 1, 0 ], 15 | [ 1, 0 ], 16 | [ 0, 1 ] 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config-flat: -------------------------------------------------------------------------------- 1 | { 2 | "hashAlgorithm": "CRC", 3 | "numReplicas": 2, 4 | "serverList": [ 5 | "server1:11211", 6 | "server2:11210", 7 | "server3:11211" 8 | ], 9 | "vBucketMap": [ 10 | [ 0, 1, 2 ], 11 | [ 1, 2, 0 ], 12 | [ 2, 1, -1 ], 13 | [ 1, 2, 0 ] 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config-in-envelope: -------------------------------------------------------------------------------- 1 | { 2 | "otherKeyThatIsIgnored": 12345, 3 | "vBucketServerMap": { 4 | "hashAlgorithm": "CRC", 5 | "numReplicas": 2, 6 | "serverList": [ 7 | "server1:11211", 8 | "server2:11210", 9 | "server3:11211" 10 | ], 11 | "vBucketMap": [ 12 | [ 0, 1, 2 ], 13 | [ 1, 2, 0 ], 14 | [ 2, 1, -1 ], 15 | [ 1, 2, 0 ] 16 | ] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config-in-envelope-fft: -------------------------------------------------------------------------------- 1 | { 2 | "otherKeyThatIsIgnored": 12345, 3 | "vBucketServerMap": { 4 | "hashAlgorithm": "CRC", 5 | "numReplicas": 2, 6 | "serverList": [ 7 | "server1:11211", 8 | "server2:11210", 9 | "server3:11211", 10 | "server4:11211" 11 | ], 12 | "vBucketMap": [ 13 | [ 0, 1, 2 ], 14 | [ 1, 2, 0 ], 15 | [ 2, 1, -1 ], 16 | [ 1, 2, 0 ] 17 | ], 18 | "vBucketMapForward": [ 19 | [ 3, 0, 0 ], 20 | [ 2, 1, 3 ], 21 | [ 1, 2, 2 ], 22 | [ 0, 3, 1 ] 23 | ] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config-in-envelope2: -------------------------------------------------------------------------------- 1 | { 2 | "name": "default", 3 | "uri": "/pools/default/buckets/default", 4 | "streamingUri": "/pools/default/bucketsStreaming/default", 5 | "flushCacheUri": "/pools/default/buckets/default/controller/doFlush", 6 | "nodes": [ 7 | { 8 | "clusterMembership": "inactiveAdded", 9 | "status": "unhealthy", 10 | "hostname": "127.0.0.1", 11 | "version": "unknown", 12 | "os": "unknown", 13 | "ports": { 14 | "proxy": 11213, 15 | "direct": 11212 16 | }, 17 | "uptime": "0", 18 | "memoryTotal": 0, 19 | "memoryFree": 0, 20 | "mcdMemoryReserved": 64, 21 | "mcdMemoryAllocated": 0 22 | } 23 | ], 24 | "stats": { 25 | "uri": "/pools/default/buckets/default/stats" 26 | }, 27 | "vBucketServerMap": { 28 | "hashAlgorithm": "CRC", 29 | "numReplicas": 2, 30 | "serverList": [ 31 | "server1:11211", 32 | "server2:11210", 33 | "server3:11211" 34 | ], 35 | "vBucketMap": [ 36 | [ 0, 1, 2 ], 37 | [ 1, 2, 0 ], 38 | [ 2, 1, -1 ], 39 | [ 1, 2, 0 ] 40 | ] 41 | }, 42 | "basicStats": { 43 | "cacheSize": 64, 44 | "opsPerSec": 0.0, 45 | "evictionsPerSec": 0.0, 46 | "cachePercentUsed": 0.0 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config-user-password1: -------------------------------------------------------------------------------- 1 | { 2 | "hashAlgorithm": "CRC", 3 | "numReplicas": 2, 4 | "serverList": [ 5 | "server1:11211", 6 | "server2:11210", 7 | "server3:11211" 8 | ], 9 | "name": "theUser", 10 | "saslPassword": "thePassword", 11 | "vBucketMap": [ 12 | [ 0, 1, 2 ], 13 | [ 1, 2, 0 ], 14 | [ 2, 1, -1 ], 15 | [ 1, 2, 0 ] 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config-user-password2: -------------------------------------------------------------------------------- 1 | { 2 | "hashAlgorithm": "CRC", 3 | "numReplicas": 2, 4 | "serverList": [ 5 | "server1:11211", 6 | "server2:11210", 7 | "server3:11211" 8 | ], 9 | "name": "theUserIsDifferent", 10 | "saslPassword": "thePasswordIsDifferent", 11 | "vBucketMap": [ 12 | [ 0, 1, 2 ], 13 | [ 1, 2, 0 ], 14 | [ 2, 1, -1 ], 15 | [ 1, 2, 0 ] 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config-wrong-num-vbuckets: -------------------------------------------------------------------------------- 1 | { 2 | "hashAlgorithm": "CRC", 3 | "numReplicas": 2, 4 | "serverList": [ 5 | "server1:11211", 6 | "server2:11210", 7 | "server3:11211" 8 | ], 9 | "vBucketMap": [ 10 | [ 2, 1, 0 ], 11 | [ 0, 1, 2 ], 12 | [ 1, 2, 0 ], 13 | [ 2, 1, -1 ], 14 | [ 1, 2, 0 ] 15 | ] 16 | } 17 | -------------------------------------------------------------------------------- /tests/vbucket/config/testapp-config-zero-num-vbuckets: -------------------------------------------------------------------------------- 1 | { 2 | "hashAlgorithm": "CRC", 3 | "numReplicas": 2, 4 | "serverList": [ 5 | "server1:11211", 6 | "server2:11210", 7 | "server3:11211" 8 | ], 9 | "vBucketMap": [] 10 | } 11 | -------------------------------------------------------------------------------- /tests/vbucket/macros.h: -------------------------------------------------------------------------------- 1 | #ifndef TESTS_MACROS_H 2 | #define TESTS_MACROS_H 3 | 4 | #include 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /tests/vbucket/regression.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | #undef NDEBUG 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include "macros.h" 12 | 13 | const char *test_cases[] = { 14 | "regression-bug2112", 15 | NULL 16 | }; 17 | 18 | int main(int argc, char **argv) { 19 | char *root = getenv("CMAKE_CURRENT_SOURCE_DIR"); 20 | char buffer[FILENAME_MAX]; 21 | VBUCKET_CONFIG_HANDLE h; 22 | char key1[9] = "00000000"; 23 | int v, m, num_replicas, ff; 24 | const char *master; 25 | 26 | if (root == NULL) { 27 | if (argc > 1) { 28 | root = argv[1]; 29 | } else { 30 | root = "."; 31 | } 32 | } 33 | 34 | for (ff = 0; test_cases[ff] != NULL; ++ff) { 35 | sprintf(buffer, "%s/tests/vbucket/config/%s", root, test_cases[ff]); 36 | fprintf(stderr, "Running regression test for: %s\n", test_cases[ff]); 37 | h = vbucket_config_create(); 38 | cb_assert(vbucket_config_parse(h, LIBVBUCKET_SOURCE_FILE, buffer) == 0); 39 | 40 | fprintf(stderr, "Testing a key can be hashed."); 41 | v = vbucket_get_vbucket_by_key(h, key1, strlen(key1)); 42 | m = vbucket_get_master(h, v); 43 | master = vbucket_config_get_server(h, m); 44 | fprintf(stderr, " key: %s vBucketId: %d master: %s", key1, v, master); 45 | num_replicas = vbucket_config_get_num_replicas(h); 46 | if (num_replicas > 0) { 47 | int j; 48 | fprintf(stderr, " replicas:"); 49 | for (j = 0; j < num_replicas; j++) { 50 | int r = vbucket_get_replica(h, v, j); 51 | if (r >= 0) { 52 | const char *replica = vbucket_config_get_server(h, r); 53 | fprintf(stderr, " %s", replica == NULL ? "(null)" : replica); 54 | } 55 | } 56 | } 57 | fprintf(stderr, "\n"); 58 | vbucket_config_destroy(h); 59 | } 60 | 61 | exit(EXIT_SUCCESS); 62 | } 63 | -------------------------------------------------------------------------------- /tests/vbucket/testketama.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | 3 | #undef NDEBUG 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include "vbucket/hash.h" 12 | #include "macros.h" 13 | 14 | #define NKEY 10 15 | 16 | static void read_checksum(const char *path, unsigned char *result) { 17 | FILE *ff = fopen(path, "r"); 18 | int ii, nn; 19 | for (ii = 0; ii < 16; ++ii) { 20 | nn = fscanf(ff, "%2x", (unsigned int *)&result[ii]); 21 | if (nn != 1) { 22 | perror("scanf"); 23 | abort(); 24 | } 25 | } 26 | } 27 | 28 | const char *test_cases[] = { 29 | "ketama-eight-nodes", 30 | "ketama-ordered-eight-nodes", 31 | NULL 32 | }; 33 | 34 | int main(void) { 35 | char *root = getenv("srcdir"); 36 | const char *host; 37 | char buffer[FILENAME_MAX]; 38 | char key[NKEY]; 39 | int idx, i, len, ff; 40 | VBUCKET_CONFIG_HANDLE vb; 41 | unsigned char checksum[16]; 42 | unsigned char expected[16]; 43 | void *ctx; 44 | 45 | if (root != NULL) { 46 | for (ff = 0; test_cases[ff] != NULL; ++ff) { 47 | snprintf(buffer, FILENAME_MAX, "%s/tests/vbucket/config/%s", root, test_cases[ff]); 48 | fprintf(stderr, "Running ketama test for: %s\n", test_cases[ff]); 49 | vb = vbucket_config_create(); 50 | cb_assert(vbucket_config_parse(vb, LIBVBUCKET_SOURCE_FILE, buffer) == 0); 51 | /* check if it conforms to libketama results */ 52 | snprintf(buffer, FILENAME_MAX,"%s/tests/vbucket/config/%s.md5sum", root, test_cases[ff]); 53 | read_checksum(buffer, expected); 54 | memset(checksum, 0, 16); 55 | ctx = NULL; 56 | 57 | for (i = 0; i < 1000000; i++) { 58 | len = snprintf(key, NKEY, "%d", i); 59 | vbucket_map(vb, key, len, NULL, &idx); 60 | host = vbucket_config_get_server(vb, idx); 61 | ctx = hash_md5_update(ctx, host, strlen(host)); 62 | } 63 | hash_md5_final(ctx, checksum); 64 | 65 | for (i = 0; i < 16; i++) { 66 | cb_assert(checksum[i] == expected[i]); 67 | } 68 | 69 | vbucket_config_destroy(vb); 70 | } 71 | } 72 | 73 | exit(EXIT_SUCCESS); 74 | } 75 | -------------------------------------------------------------------------------- /vbucket/hash.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | /* 3 | * Copyright 2010 NorthScale, Inc. 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | #ifndef LIBVBUCKET_HASH_H 18 | #define LIBVBUCKET_HASH_H 1 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | uint32_t hash_crc32(const char *key, size_t key_length); 25 | uint32_t hash_ketama(const char *key, size_t key_length); 26 | void hash_md5(const char *key, size_t key_length, unsigned char *result); 27 | 28 | void* hash_md5_update(void *ctx, const char *key, size_t key_length); 29 | void hash_md5_final(void *ctx, unsigned char *result); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /vbucket/ketama.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | #include 3 | #include "hash.h" 4 | 5 | /* This library uses the reference MD5 implementation from [RFC1321] */ 6 | #define PROTOTYPES 1 7 | #include "rfc1321/md5c.c" 8 | #undef PROTOTYPES 9 | 10 | void hash_md5(const char *key, size_t key_length, unsigned char *result) 11 | { 12 | MD5_CTX ctx; 13 | 14 | MD5Init(&ctx); 15 | MD5Update(&ctx, (unsigned char *)key, key_length); 16 | MD5Final(result, &ctx); 17 | } 18 | 19 | void* hash_md5_update(void *ctx, const char *key, size_t key_length) 20 | { 21 | if (ctx == NULL) { 22 | ctx = calloc(1, sizeof(MD5_CTX)); 23 | MD5Init(ctx); 24 | } 25 | MD5Update(ctx, (unsigned char *)key, key_length); 26 | return ctx; 27 | } 28 | 29 | void hash_md5_final(void *ctx, unsigned char *result) 30 | { 31 | if (ctx == NULL) { 32 | return; 33 | } 34 | MD5Final(result, ctx); 35 | free(ctx); 36 | } 37 | 38 | uint32_t hash_ketama(const char *key, size_t key_length) 39 | { 40 | unsigned char digest[16]; 41 | 42 | hash_md5(key, key_length, digest); 43 | 44 | return (uint32_t) ( (digest[3] << 24) 45 | |(digest[2] << 16) 46 | |(digest[1] << 8) 47 | | digest[0]); 48 | } 49 | -------------------------------------------------------------------------------- /vbucket/rfc1321/global.h: -------------------------------------------------------------------------------- 1 | /* GLOBAL.H - RSAREF types and constants 2 | */ 3 | 4 | /* PROTOTYPES should be set to one if and only if the compiler supports 5 | function argument prototyping. 6 | The following makes PROTOTYPES default to 0 if it has not already 7 | been defined with C compiler flags. 8 | */ 9 | #ifndef PROTOTYPES 10 | #define PROTOTYPES 0 11 | #endif 12 | 13 | #include 14 | 15 | /* POINTER defines a generic pointer type */ 16 | typedef unsigned char *POINTER; 17 | 18 | /* UINT2 defines a two byte word */ 19 | typedef uint16_t UINT2; 20 | 21 | /* UINT4 defines a four byte word */ 22 | typedef uint32_t UINT4; 23 | 24 | /* PROTO_LIST is defined depending on how PROTOTYPES is defined above. 25 | If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it 26 | returns an empty list. 27 | */ 28 | #if PROTOTYPES 29 | #define PROTO_LIST(list) list 30 | #else 31 | #define PROTO_LIST(list) () 32 | #endif 33 | -------------------------------------------------------------------------------- /vbucket/rfc1321/md5.h: -------------------------------------------------------------------------------- 1 | /* MD5.H - header file for MD5C.C 2 | */ 3 | 4 | /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 5 | rights reserved. 6 | 7 | License to copy and use this software is granted provided that it 8 | is identified as the "RSA Data Security, Inc. MD5 Message-Digest 9 | Algorithm" in all material mentioning or referencing this software 10 | or this function. 11 | 12 | License is also granted to make and use derivative works provided 13 | that such works are identified as "derived from the RSA Data 14 | Security, Inc. MD5 Message-Digest Algorithm" in all material 15 | mentioning or referencing the derived work. 16 | 17 | RSA Data Security, Inc. makes no representations concerning either 18 | the merchantability of this software or the suitability of this 19 | software for any particular purpose. It is provided "as is" 20 | without express or implied warranty of any kind. 21 | 22 | These notices must be retained in any copies of any part of this 23 | documentation and/or software. 24 | */ 25 | 26 | /* MD5 context. */ 27 | typedef struct { 28 | UINT4 state[4]; /* state (ABCD) */ 29 | UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */ 30 | unsigned char buffer[64]; /* input buffer */ 31 | } MD5_CTX; 32 | 33 | void MD5Init PROTO_LIST ((MD5_CTX *)); 34 | void MD5Update PROTO_LIST ((MD5_CTX *, unsigned char *, unsigned int)); 35 | void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *)); 36 | --------------------------------------------------------------------------------