├── AUTHORS ├── ChangeLog ├── INSTALL ├── LICENSE ├── Makefile.am ├── Makefile.in ├── README ├── TODO ├── aclocal.m4 ├── autogen.sh ├── bdb.c ├── compile ├── config.h.in ├── configure ├── configure.ac ├── daemon.c ├── depcomp ├── docgen.sh ├── hash.c ├── hash.h ├── hashtable.c ├── hashtable.h ├── install-sh ├── item.c ├── memcacheq.c ├── memcacheq.h ├── missing ├── run.sh ├── thread.c └── tools ├── Makefile.am ├── Makefile.in ├── memcache.py ├── mqpop.py └── mqpush.py /AUTHORS: -------------------------------------------------------------------------------- 1 | Steve Chu 2 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | 2014-12-17 Steve Chu 2 | * version 0.2.1 is released. 3 | 4 | 2014-12-16 Steve Chu 5 | * disable udp by default, udp code is buggy and for reliable message, better not to use it :p 6 | 7 | 2010-08-12 Steve Chu 8 | * fix a lock bug when creating queue 9 | 10 | 2009-12-09 Steve Chu 11 | * version 0.2.0 is released. 12 | 13 | 2009-12-09 Steve Chu 14 | * the multiple queue map code is rewritten, now we support instant per-queue statistics. telnet and type 'stats queue' command for detail. 15 | * tools are added for 'stats queue', check 'tools/'. 16 | * a new option(-R) is added to remove useless transaction log automatically. 17 | * some code clearup 18 | 19 | 2008-11-25 Steve Chu 20 | * version 0.1.1 is released. 21 | 22 | 2008-11-25 Steve Chu 23 | * Bugfix: 'stats queue' did not return right queue name 24 | * All replication code has been discarded and removed. Original replication 25 | code is buggy, also nobody want to use replication on a message queue system. 26 | * more graceful exit 27 | 28 | 2008-09-19 Steve Chu 29 | * version 0.1.0 is released. 30 | 31 | 2008-09-19 Steve Chu 32 | * All code is rewritten based on latest memcachedb, and multiple queue is supported. 33 | Please see 'README.html' for usage. 34 | 35 | 2008-03-17 Steve Chu 36 | * add a '-A' option to set page size 37 | 38 | 2008-03-15 Steve Chu 39 | * version 0.0.1 is released. 40 | 41 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Dependencies 2 | ============ 3 | Before deploying MemcacheQ, make sure that following packages have been installed: 4 | 5 | Berkeley DB 4.7 or later 6 | ------------------------- 7 | 8 | Download from 9 | 10 | How to install BerkekeyDB:: 11 | 12 | $tar xvzf db-4.7.25.tar.gz 13 | $cd db-4.7.25/ 14 | $cd build_unix/ 15 | $../dist/configure 16 | $make 17 | $sudo make install 18 | 19 | 20 | libevent 1.4.x or later 21 | ----------------------- 22 | 23 | Download from 24 | 25 | How to install libevent:: 26 | 27 | $tar xvzf libevent-1.4.x-stable.tar.gz 28 | $cd libevent-1.4.x-stable 29 | $./configure 30 | $make 31 | $sudo make install 32 | 33 | On a linux, load .so file by add two line in /etc/ld.so.conf:: 34 | 35 | /usr/local/lib 36 | /usr/local/BerkeleyDB.4.7/lib 37 | 38 | Then, run 'ldconfig'. 39 | 40 | Building MemcacheQ 41 | ================== 42 | 43 | On a \*nix, just following:: 44 | 45 | $tar xvzf memcacheq-0.2.x.tar.gz 46 | $cd memcacheq-0.2.x 47 | $./configure --enable-threads 48 | $make 49 | $sudo make install 50 | 51 | Start the daemon 52 | ================ 53 | 54 | For example:: 55 | 56 | memcacheq -d -r -H /data1/memcacheq -N -R -v -L 1024 -B 1024 > /data1/mq_error.log 2>&1 57 | 58 | 59 | Stop the daemon 60 | =============== 61 | It is safe to call 'kill ' directly to stop the daemon. But be careful with kill -9. 62 | 63 | Notice 64 | ======= 65 | Because MemcacheQ is using fixed-length storage, so you should use '-B' option to specify the max length of your message. Default is 1024 bytes. Any message that shorter than the length you specified will be padded with '0x20', the space character. A message includes following bytes:: 66 | 67 | + + 68 | 69 | Use "-h" option to see more configures. 70 | 71 | Have fun :) 72 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2008, Steve Chu. 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 author 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 | 32 | 33 | This product includes software developed by Danga Interactive, Inc. 34 | 35 | [ memcached ] 36 | 37 | Copyright (c) 2003, Danga Interactive, Inc. 38 | All rights reserved. 39 | 40 | Redistribution and use in source and binary forms, with or without 41 | modification, are permitted provided that the following conditions are 42 | met: 43 | 44 | * Redistributions of source code must retain the above copyright 45 | notice, this list of conditions and the following disclaimer. 46 | 47 | * Redistributions in binary form must reproduce the above 48 | copyright notice, this list of conditions and the following disclaimer 49 | in the documentation and/or other materials provided with the 50 | distribution. 51 | 52 | * Neither the name of the Danga Interactive nor the names of its 53 | contributors may be used to endorse or promote products derived from 54 | this software without specific prior written permission. 55 | 56 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 57 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 58 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 59 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 60 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 61 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 62 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 63 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 64 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 65 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 66 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 67 | 68 | 69 | This product includes software developed by Niels Provos. 70 | 71 | [ libevent ] 72 | 73 | Copyright 2000-2003 Niels Provos 74 | All rights reserved. 75 | 76 | Redistribution and use in source and binary forms, with or without 77 | modification, are permitted provided that the following conditions 78 | are met: 79 | 1. Redistributions of source code must retain the above copyright 80 | notice, this list of conditions and the following disclaimer. 81 | 2. Redistributions in binary form must reproduce the above copyright 82 | notice, this list of conditions and the following disclaimer in the 83 | documentation and/or other materials provided with the distribution. 84 | 3. All advertising materials mentioning features or use of this software 85 | must display the following acknowledgement: 86 | This product includes software developed by Niels Provos. 87 | 4. The name of the author may not be used to endorse or promote products 88 | derived from this software without specific prior written permission. 89 | 90 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 91 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 92 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 93 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 94 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 95 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 96 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 97 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 98 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 99 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 100 | 101 | 102 | This product includes software developed by Oracle Inc. 103 | 104 | [ BerkeleyDB ] 105 | 106 | See LICENSE file in BerkeleyDB distribution to get more Copyright info. 107 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | bin_PROGRAMS = memcacheq 2 | memcacheq_SOURCES = memcacheq.c item.c memcacheq.h thread.c bdb.c hashtable.h hashtable.c hash.h hash.c daemon.c 3 | 4 | EXTRA_DIST = tools AUTHORS LICENSE run.sh 5 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.10 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 5 | # 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 6 | # This Makefile.in is free software; the Free Software Foundation 7 | # gives unlimited permission to copy and/or distribute it, 8 | # with or without modifications, as long as this notice is preserved. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 12 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | # PARTICULAR PURPOSE. 14 | 15 | @SET_MAKE@ 16 | 17 | VPATH = @srcdir@ 18 | pkgdatadir = $(datadir)/@PACKAGE@ 19 | pkglibdir = $(libdir)/@PACKAGE@ 20 | pkgincludedir = $(includedir)/@PACKAGE@ 21 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 22 | install_sh_DATA = $(install_sh) -c -m 644 23 | install_sh_PROGRAM = $(install_sh) -c 24 | install_sh_SCRIPT = $(install_sh) -c 25 | INSTALL_HEADER = $(INSTALL_DATA) 26 | transform = $(program_transform_name) 27 | NORMAL_INSTALL = : 28 | PRE_INSTALL = : 29 | POST_INSTALL = : 30 | NORMAL_UNINSTALL = : 31 | PRE_UNINSTALL = : 32 | POST_UNINSTALL = : 33 | bin_PROGRAMS = memcacheq$(EXEEXT) 34 | subdir = . 35 | DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \ 36 | $(srcdir)/Makefile.in $(srcdir)/config.h.in \ 37 | $(top_srcdir)/configure AUTHORS ChangeLog INSTALL TODO compile \ 38 | depcomp install-sh missing 39 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 40 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac 41 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 42 | $(ACLOCAL_M4) 43 | am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ 44 | configure.lineno config.status.lineno 45 | mkinstalldirs = $(install_sh) -d 46 | CONFIG_HEADER = config.h 47 | CONFIG_CLEAN_FILES = 48 | am__installdirs = "$(DESTDIR)$(bindir)" 49 | binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) 50 | PROGRAMS = $(bin_PROGRAMS) 51 | am_memcacheq_OBJECTS = memcacheq.$(OBJEXT) item.$(OBJEXT) \ 52 | thread.$(OBJEXT) bdb.$(OBJEXT) hashtable.$(OBJEXT) \ 53 | hash.$(OBJEXT) daemon.$(OBJEXT) 54 | memcacheq_OBJECTS = $(am_memcacheq_OBJECTS) 55 | memcacheq_LDADD = $(LDADD) 56 | DEFAULT_INCLUDES = -I.@am__isrc@ 57 | depcomp = $(SHELL) $(top_srcdir)/depcomp 58 | am__depfiles_maybe = depfiles 59 | COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ 60 | $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) 61 | CCLD = $(CC) 62 | LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@ 63 | SOURCES = $(memcacheq_SOURCES) 64 | DIST_SOURCES = $(memcacheq_SOURCES) 65 | ETAGS = etags 66 | CTAGS = ctags 67 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 68 | distdir = $(PACKAGE)-$(VERSION) 69 | top_distdir = $(distdir) 70 | am__remove_distdir = \ 71 | { test ! -d $(distdir) \ 72 | || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ 73 | && rm -fr $(distdir); }; } 74 | DIST_ARCHIVES = $(distdir).tar.gz 75 | GZIP_ENV = --best 76 | distuninstallcheck_listfiles = find . -type f -print 77 | distcleancheck_listfiles = find . -type f -print 78 | ACLOCAL = @ACLOCAL@ 79 | AMTAR = @AMTAR@ 80 | AUTOCONF = @AUTOCONF@ 81 | AUTOHEADER = @AUTOHEADER@ 82 | AUTOMAKE = @AUTOMAKE@ 83 | AWK = @AWK@ 84 | CC = @CC@ 85 | CCDEPMODE = @CCDEPMODE@ 86 | CFLAGS = @CFLAGS@ 87 | CPP = @CPP@ 88 | CPPFLAGS = @CPPFLAGS@ 89 | CYGPATH_W = @CYGPATH_W@ 90 | DEFS = @DEFS@ 91 | DEPDIR = @DEPDIR@ 92 | ECHO_C = @ECHO_C@ 93 | ECHO_N = @ECHO_N@ 94 | ECHO_T = @ECHO_T@ 95 | EGREP = @EGREP@ 96 | EXEEXT = @EXEEXT@ 97 | GREP = @GREP@ 98 | INSTALL = @INSTALL@ 99 | INSTALL_DATA = @INSTALL_DATA@ 100 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 101 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 102 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 103 | LDFLAGS = @LDFLAGS@ 104 | LIBOBJS = @LIBOBJS@ 105 | LIBS = @LIBS@ 106 | LTLIBOBJS = @LTLIBOBJS@ 107 | MAKEINFO = @MAKEINFO@ 108 | MKDIR_P = @MKDIR_P@ 109 | OBJEXT = @OBJEXT@ 110 | PACKAGE = @PACKAGE@ 111 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 112 | PACKAGE_NAME = @PACKAGE_NAME@ 113 | PACKAGE_STRING = @PACKAGE_STRING@ 114 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 115 | PACKAGE_VERSION = @PACKAGE_VERSION@ 116 | PATH_SEPARATOR = @PATH_SEPARATOR@ 117 | SET_MAKE = @SET_MAKE@ 118 | SHELL = @SHELL@ 119 | STRIP = @STRIP@ 120 | VERSION = @VERSION@ 121 | abs_builddir = @abs_builddir@ 122 | abs_srcdir = @abs_srcdir@ 123 | abs_top_builddir = @abs_top_builddir@ 124 | abs_top_srcdir = @abs_top_srcdir@ 125 | ac_ct_CC = @ac_ct_CC@ 126 | am__include = @am__include@ 127 | am__leading_dot = @am__leading_dot@ 128 | am__quote = @am__quote@ 129 | am__tar = @am__tar@ 130 | am__untar = @am__untar@ 131 | bindir = @bindir@ 132 | build_alias = @build_alias@ 133 | builddir = @builddir@ 134 | datadir = @datadir@ 135 | datarootdir = @datarootdir@ 136 | docdir = @docdir@ 137 | dvidir = @dvidir@ 138 | exec_prefix = @exec_prefix@ 139 | host_alias = @host_alias@ 140 | htmldir = @htmldir@ 141 | includedir = @includedir@ 142 | infodir = @infodir@ 143 | install_sh = @install_sh@ 144 | libdir = @libdir@ 145 | libexecdir = @libexecdir@ 146 | localedir = @localedir@ 147 | localstatedir = @localstatedir@ 148 | mandir = @mandir@ 149 | mkdir_p = @mkdir_p@ 150 | oldincludedir = @oldincludedir@ 151 | pdfdir = @pdfdir@ 152 | prefix = @prefix@ 153 | program_transform_name = @program_transform_name@ 154 | psdir = @psdir@ 155 | sbindir = @sbindir@ 156 | sharedstatedir = @sharedstatedir@ 157 | srcdir = @srcdir@ 158 | sysconfdir = @sysconfdir@ 159 | target_alias = @target_alias@ 160 | top_builddir = @top_builddir@ 161 | top_srcdir = @top_srcdir@ 162 | memcacheq_SOURCES = memcacheq.c item.c memcacheq.h thread.c bdb.c hashtable.h hashtable.c hash.h hash.c daemon.c 163 | EXTRA_DIST = tools AUTHORS LICENSE run.sh 164 | all: config.h 165 | $(MAKE) $(AM_MAKEFLAGS) all-am 166 | 167 | .SUFFIXES: 168 | .SUFFIXES: .c .o .obj 169 | am--refresh: 170 | @: 171 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 172 | @for dep in $?; do \ 173 | case '$(am__configure_deps)' in \ 174 | *$$dep*) \ 175 | echo ' cd $(srcdir) && $(AUTOMAKE) --foreign '; \ 176 | cd $(srcdir) && $(AUTOMAKE) --foreign \ 177 | && exit 0; \ 178 | exit 1;; \ 179 | esac; \ 180 | done; \ 181 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ 182 | cd $(top_srcdir) && \ 183 | $(AUTOMAKE) --foreign Makefile 184 | .PRECIOUS: Makefile 185 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 186 | @case '$?' in \ 187 | *config.status*) \ 188 | echo ' $(SHELL) ./config.status'; \ 189 | $(SHELL) ./config.status;; \ 190 | *) \ 191 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ 192 | cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ 193 | esac; 194 | 195 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 196 | $(SHELL) ./config.status --recheck 197 | 198 | $(top_srcdir)/configure: $(am__configure_deps) 199 | cd $(srcdir) && $(AUTOCONF) 200 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 201 | cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) 202 | 203 | config.h: stamp-h1 204 | @if test ! -f $@; then \ 205 | rm -f stamp-h1; \ 206 | $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \ 207 | else :; fi 208 | 209 | stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status 210 | @rm -f stamp-h1 211 | cd $(top_builddir) && $(SHELL) ./config.status config.h 212 | $(srcdir)/config.h.in: $(am__configure_deps) 213 | cd $(top_srcdir) && $(AUTOHEADER) 214 | rm -f stamp-h1 215 | touch $@ 216 | 217 | distclean-hdr: 218 | -rm -f config.h stamp-h1 219 | install-binPROGRAMS: $(bin_PROGRAMS) 220 | @$(NORMAL_INSTALL) 221 | test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" 222 | @list='$(bin_PROGRAMS)'; for p in $$list; do \ 223 | p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ 224 | if test -f $$p \ 225 | ; then \ 226 | f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ 227 | echo " $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(bindir)/$$f'"; \ 228 | $(INSTALL_PROGRAM_ENV) $(binPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(bindir)/$$f" || exit 1; \ 229 | else :; fi; \ 230 | done 231 | 232 | uninstall-binPROGRAMS: 233 | @$(NORMAL_UNINSTALL) 234 | @list='$(bin_PROGRAMS)'; for p in $$list; do \ 235 | f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ 236 | echo " rm -f '$(DESTDIR)$(bindir)/$$f'"; \ 237 | rm -f "$(DESTDIR)$(bindir)/$$f"; \ 238 | done 239 | 240 | clean-binPROGRAMS: 241 | -test -z "$(bin_PROGRAMS)" || rm -f $(bin_PROGRAMS) 242 | memcacheq$(EXEEXT): $(memcacheq_OBJECTS) $(memcacheq_DEPENDENCIES) 243 | @rm -f memcacheq$(EXEEXT) 244 | $(LINK) $(memcacheq_OBJECTS) $(memcacheq_LDADD) $(LIBS) 245 | 246 | mostlyclean-compile: 247 | -rm -f *.$(OBJEXT) 248 | 249 | distclean-compile: 250 | -rm -f *.tab.c 251 | 252 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bdb.Po@am__quote@ 253 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/daemon.Po@am__quote@ 254 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hash.Po@am__quote@ 255 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hashtable.Po@am__quote@ 256 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/item.Po@am__quote@ 257 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/memcacheq.Po@am__quote@ 258 | @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/thread.Po@am__quote@ 259 | 260 | .c.o: 261 | @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< 262 | @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po 263 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ 264 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 265 | @am__fastdepCC_FALSE@ $(COMPILE) -c $< 266 | 267 | .c.obj: 268 | @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` 269 | @am__fastdepCC_TRUE@ mv -f $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po 270 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ 271 | @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ 272 | @am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` 273 | 274 | ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) 275 | list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ 276 | unique=`for i in $$list; do \ 277 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 278 | done | \ 279 | $(AWK) ' { files[$$0] = 1; } \ 280 | END { for (i in files) print i; }'`; \ 281 | mkid -fID $$unique 282 | tags: TAGS 283 | 284 | TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ 285 | $(TAGS_FILES) $(LISP) 286 | tags=; \ 287 | here=`pwd`; \ 288 | list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ 289 | unique=`for i in $$list; do \ 290 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 291 | done | \ 292 | $(AWK) ' { files[$$0] = 1; } \ 293 | END { for (i in files) print i; }'`; \ 294 | if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \ 295 | test -n "$$unique" || unique=$$empty_fix; \ 296 | $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ 297 | $$tags $$unique; \ 298 | fi 299 | ctags: CTAGS 300 | CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ 301 | $(TAGS_FILES) $(LISP) 302 | tags=; \ 303 | here=`pwd`; \ 304 | list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ 305 | unique=`for i in $$list; do \ 306 | if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ 307 | done | \ 308 | $(AWK) ' { files[$$0] = 1; } \ 309 | END { for (i in files) print i; }'`; \ 310 | test -z "$(CTAGS_ARGS)$$tags$$unique" \ 311 | || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ 312 | $$tags $$unique 313 | 314 | GTAGS: 315 | here=`$(am__cd) $(top_builddir) && pwd` \ 316 | && cd $(top_srcdir) \ 317 | && gtags -i $(GTAGS_ARGS) $$here 318 | 319 | distclean-tags: 320 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags 321 | 322 | distdir: $(DISTFILES) 323 | $(am__remove_distdir) 324 | test -d $(distdir) || mkdir $(distdir) 325 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 326 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 327 | list='$(DISTFILES)'; \ 328 | dist_files=`for file in $$list; do echo $$file; done | \ 329 | sed -e "s|^$$srcdirstrip/||;t" \ 330 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 331 | case $$dist_files in \ 332 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 333 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 334 | sort -u` ;; \ 335 | esac; \ 336 | for file in $$dist_files; do \ 337 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 338 | if test -d $$d/$$file; then \ 339 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 340 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 341 | cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ 342 | fi; \ 343 | cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ 344 | else \ 345 | test -f $(distdir)/$$file \ 346 | || cp -p $$d/$$file $(distdir)/$$file \ 347 | || exit 1; \ 348 | fi; \ 349 | done 350 | -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ 351 | ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ 352 | ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ 353 | ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ 354 | || chmod -R a+r $(distdir) 355 | dist-gzip: distdir 356 | tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz 357 | $(am__remove_distdir) 358 | 359 | dist-bzip2: distdir 360 | tardir=$(distdir) && $(am__tar) | bzip2 -9 -c >$(distdir).tar.bz2 361 | $(am__remove_distdir) 362 | 363 | dist-tarZ: distdir 364 | tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z 365 | $(am__remove_distdir) 366 | 367 | dist-shar: distdir 368 | shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz 369 | $(am__remove_distdir) 370 | 371 | dist-zip: distdir 372 | -rm -f $(distdir).zip 373 | zip -rq $(distdir).zip $(distdir) 374 | $(am__remove_distdir) 375 | 376 | dist dist-all: distdir 377 | tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz 378 | $(am__remove_distdir) 379 | 380 | # This target untars the dist file and tries a VPATH configuration. Then 381 | # it guarantees that the distribution is self-contained by making another 382 | # tarfile. 383 | distcheck: dist 384 | case '$(DIST_ARCHIVES)' in \ 385 | *.tar.gz*) \ 386 | GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(am__untar) ;;\ 387 | *.tar.bz2*) \ 388 | bunzip2 -c $(distdir).tar.bz2 | $(am__untar) ;;\ 389 | *.tar.Z*) \ 390 | uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ 391 | *.shar.gz*) \ 392 | GZIP=$(GZIP_ENV) gunzip -c $(distdir).shar.gz | unshar ;;\ 393 | *.zip*) \ 394 | unzip $(distdir).zip ;;\ 395 | esac 396 | chmod -R a-w $(distdir); chmod a+w $(distdir) 397 | mkdir $(distdir)/_build 398 | mkdir $(distdir)/_inst 399 | chmod a-w $(distdir) 400 | dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ 401 | && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ 402 | && cd $(distdir)/_build \ 403 | && ../configure --srcdir=.. --prefix="$$dc_install_base" \ 404 | $(DISTCHECK_CONFIGURE_FLAGS) \ 405 | && $(MAKE) $(AM_MAKEFLAGS) \ 406 | && $(MAKE) $(AM_MAKEFLAGS) dvi \ 407 | && $(MAKE) $(AM_MAKEFLAGS) check \ 408 | && $(MAKE) $(AM_MAKEFLAGS) install \ 409 | && $(MAKE) $(AM_MAKEFLAGS) installcheck \ 410 | && $(MAKE) $(AM_MAKEFLAGS) uninstall \ 411 | && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ 412 | distuninstallcheck \ 413 | && chmod -R a-w "$$dc_install_base" \ 414 | && ({ \ 415 | (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ 416 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ 417 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ 418 | && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ 419 | distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ 420 | } || { rm -rf "$$dc_destdir"; exit 1; }) \ 421 | && rm -rf "$$dc_destdir" \ 422 | && $(MAKE) $(AM_MAKEFLAGS) dist \ 423 | && rm -rf $(DIST_ARCHIVES) \ 424 | && $(MAKE) $(AM_MAKEFLAGS) distcleancheck 425 | $(am__remove_distdir) 426 | @(echo "$(distdir) archives ready for distribution: "; \ 427 | list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ 428 | sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' 429 | distuninstallcheck: 430 | @cd $(distuninstallcheck_dir) \ 431 | && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ 432 | || { echo "ERROR: files left after uninstall:" ; \ 433 | if test -n "$(DESTDIR)"; then \ 434 | echo " (check DESTDIR support)"; \ 435 | fi ; \ 436 | $(distuninstallcheck_listfiles) ; \ 437 | exit 1; } >&2 438 | distcleancheck: distclean 439 | @if test '$(srcdir)' = . ; then \ 440 | echo "ERROR: distcleancheck can only run from a VPATH build" ; \ 441 | exit 1 ; \ 442 | fi 443 | @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ 444 | || { echo "ERROR: files left in build directory after distclean:" ; \ 445 | $(distcleancheck_listfiles) ; \ 446 | exit 1; } >&2 447 | check-am: all-am 448 | check: check-am 449 | all-am: Makefile $(PROGRAMS) config.h 450 | installdirs: 451 | for dir in "$(DESTDIR)$(bindir)"; do \ 452 | test -z "$$dir" || $(MKDIR_P) "$$dir"; \ 453 | done 454 | install: install-am 455 | install-exec: install-exec-am 456 | install-data: install-data-am 457 | uninstall: uninstall-am 458 | 459 | install-am: all-am 460 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 461 | 462 | installcheck: installcheck-am 463 | install-strip: 464 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 465 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 466 | `test -z '$(STRIP)' || \ 467 | echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 468 | mostlyclean-generic: 469 | 470 | clean-generic: 471 | 472 | distclean-generic: 473 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 474 | 475 | maintainer-clean-generic: 476 | @echo "This command is intended for maintainers to use" 477 | @echo "it deletes files that may require special tools to rebuild." 478 | clean: clean-am 479 | 480 | clean-am: clean-binPROGRAMS clean-generic mostlyclean-am 481 | 482 | distclean: distclean-am 483 | -rm -f $(am__CONFIG_DISTCLEAN_FILES) 484 | -rm -rf ./$(DEPDIR) 485 | -rm -f Makefile 486 | distclean-am: clean-am distclean-compile distclean-generic \ 487 | distclean-hdr distclean-tags 488 | 489 | dvi: dvi-am 490 | 491 | dvi-am: 492 | 493 | html: html-am 494 | 495 | info: info-am 496 | 497 | info-am: 498 | 499 | install-data-am: 500 | 501 | install-dvi: install-dvi-am 502 | 503 | install-exec-am: install-binPROGRAMS 504 | 505 | install-html: install-html-am 506 | 507 | install-info: install-info-am 508 | 509 | install-man: 510 | 511 | install-pdf: install-pdf-am 512 | 513 | install-ps: install-ps-am 514 | 515 | installcheck-am: 516 | 517 | maintainer-clean: maintainer-clean-am 518 | -rm -f $(am__CONFIG_DISTCLEAN_FILES) 519 | -rm -rf $(top_srcdir)/autom4te.cache 520 | -rm -rf ./$(DEPDIR) 521 | -rm -f Makefile 522 | maintainer-clean-am: distclean-am maintainer-clean-generic 523 | 524 | mostlyclean: mostlyclean-am 525 | 526 | mostlyclean-am: mostlyclean-compile mostlyclean-generic 527 | 528 | pdf: pdf-am 529 | 530 | pdf-am: 531 | 532 | ps: ps-am 533 | 534 | ps-am: 535 | 536 | uninstall-am: uninstall-binPROGRAMS 537 | 538 | .MAKE: install-am install-strip 539 | 540 | .PHONY: CTAGS GTAGS all all-am am--refresh check check-am clean \ 541 | clean-binPROGRAMS clean-generic ctags dist dist-all dist-bzip2 \ 542 | dist-gzip dist-shar dist-tarZ dist-zip distcheck distclean \ 543 | distclean-compile distclean-generic distclean-hdr \ 544 | distclean-tags distcleancheck distdir distuninstallcheck dvi \ 545 | dvi-am html html-am info info-am install install-am \ 546 | install-binPROGRAMS install-data install-data-am install-dvi \ 547 | install-dvi-am install-exec install-exec-am install-html \ 548 | install-html-am install-info install-info-am install-man \ 549 | install-pdf install-pdf-am install-ps install-ps-am \ 550 | install-strip installcheck installcheck-am installdirs \ 551 | maintainer-clean maintainer-clean-generic mostlyclean \ 552 | mostlyclean-compile mostlyclean-generic pdf pdf-am ps ps-am \ 553 | tags uninstall uninstall-am uninstall-binPROGRAMS 554 | 555 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 556 | # Otherwise a system limit (for SysV at least) may be exceeded. 557 | .NOEXPORT: 558 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | =============================================== 2 | MemcacheQ - Simple Queue Service over Memcache 3 | =============================================== 4 | 5 | Features 6 | ========= 7 | * damn simple 8 | * very fast 9 | * multiple queue 10 | * concurrent well 11 | * memcache protocol compatible 12 | 13 | Getting Started 14 | =============== 15 | 16 | Download 17 | --------- 18 | See: 19 | 20 | Installation 21 | ------------- 22 | See: 23 | 24 | Please take a look at 'ChangLog' file in the distribution, see what's new. 25 | 26 | Commands 27 | --------- 28 | 29 | Only two commands are used to operate the queue: 30 | 31 | **Append a message to the tail of queue**:: 32 | 33 | set 0 \r\n 34 | \r\n 35 | STORED\r\n 36 | 37 | **Note:** MQ will create a new queue automatically if your queue is not existed. The original 'expire time' field is ignored by server. 38 | 39 | **Consume a message from the head of queue**:: 40 | 41 | get \r\n 42 | VALUE \r\n 43 | \r\n 44 | END\r\n 45 | 46 | 47 | Examples 48 | --------- 49 | 50 | Assuming you are using PHP memcache:: 51 | 52 | 64 | 65 | Limitation 66 | =========== 67 | The message body is stored in Berkeley DB with fixed length. Any message that is shorter than the declared length will automatically be padded with space character (0x20 in the ASCII character set). 68 | 69 | In Berkeley DB, as the official document refers, 70 | 71 | "For the Queue access method, the record length must be enough smaller than the database's page size that at least one record plus the database page's metadata information can fit on each database page." 72 | 73 | "The minimum page size is 512 bytes, the maximum page size is 64K bytes, and the page size must be a power-of-two." 74 | 75 | So we have a limit on the message body size with a max of a bit less than *64K*. 76 | 77 | Other tips 78 | =========== 79 | use 'stats queue' to see your current queues:: 80 | 81 | $ telnet 127.0.0.1 22201 82 | Trying 127.0.0.1... 83 | Connected to localhost. 84 | Escape character is '^]'. 85 | stats queue 86 | STAT test1 12231/12 87 | STAT test2 23/23 88 | STAT test3 1212/12 89 | STAT test4 1/1 90 | END 91 | 92 | delete a queue:: 93 | 94 | $ telnet 127.0.0.1 22201 95 | Trying 127.0.0.1... 96 | Connected to localhost. 97 | Escape character is '^]'. 98 | delete test1 99 | DELETED 100 | 101 | 102 | Feedback 103 | ========= 104 | MemcacheDB mailing list now hosts on Google Group: http://groups.google.com/group/memcachedb 105 | 106 | * To subscribe to maillist, send email to memcachedb-subscribe@googlegroups.com 107 | * To post to maillist, send email to memcachedb@googlegroups.com 108 | * To unsubscribe from maillist, send email to memcachedb-unsubscribe@googlegroups.com 109 | 110 | Please report your bugs and issues to the Maillist. 111 | 112 | Last updated by Steve Chu: 12/09/2009 113 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stvchu/memcacheq/fc78c57d66d8190c73cf3c186b2ebf4d23ad0c92/TODO -------------------------------------------------------------------------------- /aclocal.m4: -------------------------------------------------------------------------------- 1 | # generated automatically by aclocal 1.10 -*- Autoconf -*- 2 | 3 | # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 4 | # 2005, 2006 Free Software Foundation, Inc. 5 | # This file is free software; the Free Software Foundation 6 | # gives unlimited permission to copy and/or distribute it, 7 | # with or without modifications, as long as this notice is preserved. 8 | 9 | # This program is distributed in the hope that it will be useful, 10 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 11 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 12 | # PARTICULAR PURPOSE. 13 | 14 | m4_if(m4_PACKAGE_VERSION, [2.61],, 15 | [m4_fatal([this file was generated for autoconf 2.61. 16 | You have another version of autoconf. If you want to use that, 17 | you should regenerate the build system entirely.], [63])]) 18 | 19 | # Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. 20 | # 21 | # This file is free software; the Free Software Foundation 22 | # gives unlimited permission to copy and/or distribute it, 23 | # with or without modifications, as long as this notice is preserved. 24 | 25 | # AM_AUTOMAKE_VERSION(VERSION) 26 | # ---------------------------- 27 | # Automake X.Y traces this macro to ensure aclocal.m4 has been 28 | # generated from the m4 files accompanying Automake X.Y. 29 | # (This private macro should not be called outside this file.) 30 | AC_DEFUN([AM_AUTOMAKE_VERSION], 31 | [am__api_version='1.10' 32 | dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to 33 | dnl require some minimum version. Point them to the right macro. 34 | m4_if([$1], [1.10], [], 35 | [AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl 36 | ]) 37 | 38 | # _AM_AUTOCONF_VERSION(VERSION) 39 | # ----------------------------- 40 | # aclocal traces this macro to find the Autoconf version. 41 | # This is a private macro too. Using m4_define simplifies 42 | # the logic in aclocal, which can simply ignore this definition. 43 | m4_define([_AM_AUTOCONF_VERSION], []) 44 | 45 | # AM_SET_CURRENT_AUTOMAKE_VERSION 46 | # ------------------------------- 47 | # Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced. 48 | # This function is AC_REQUIREd by AC_INIT_AUTOMAKE. 49 | AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], 50 | [AM_AUTOMAKE_VERSION([1.10])dnl 51 | _AM_AUTOCONF_VERSION(m4_PACKAGE_VERSION)]) 52 | 53 | # AM_AUX_DIR_EXPAND -*- Autoconf -*- 54 | 55 | # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. 56 | # 57 | # This file is free software; the Free Software Foundation 58 | # gives unlimited permission to copy and/or distribute it, 59 | # with or without modifications, as long as this notice is preserved. 60 | 61 | # For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets 62 | # $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to 63 | # `$srcdir', `$srcdir/..', or `$srcdir/../..'. 64 | # 65 | # Of course, Automake must honor this variable whenever it calls a 66 | # tool from the auxiliary directory. The problem is that $srcdir (and 67 | # therefore $ac_aux_dir as well) can be either absolute or relative, 68 | # depending on how configure is run. This is pretty annoying, since 69 | # it makes $ac_aux_dir quite unusable in subdirectories: in the top 70 | # source directory, any form will work fine, but in subdirectories a 71 | # relative path needs to be adjusted first. 72 | # 73 | # $ac_aux_dir/missing 74 | # fails when called from a subdirectory if $ac_aux_dir is relative 75 | # $top_srcdir/$ac_aux_dir/missing 76 | # fails if $ac_aux_dir is absolute, 77 | # fails when called from a subdirectory in a VPATH build with 78 | # a relative $ac_aux_dir 79 | # 80 | # The reason of the latter failure is that $top_srcdir and $ac_aux_dir 81 | # are both prefixed by $srcdir. In an in-source build this is usually 82 | # harmless because $srcdir is `.', but things will broke when you 83 | # start a VPATH build or use an absolute $srcdir. 84 | # 85 | # So we could use something similar to $top_srcdir/$ac_aux_dir/missing, 86 | # iff we strip the leading $srcdir from $ac_aux_dir. That would be: 87 | # am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` 88 | # and then we would define $MISSING as 89 | # MISSING="\${SHELL} $am_aux_dir/missing" 90 | # This will work as long as MISSING is not called from configure, because 91 | # unfortunately $(top_srcdir) has no meaning in configure. 92 | # However there are other variables, like CC, which are often used in 93 | # configure, and could therefore not use this "fixed" $ac_aux_dir. 94 | # 95 | # Another solution, used here, is to always expand $ac_aux_dir to an 96 | # absolute PATH. The drawback is that using absolute paths prevent a 97 | # configured tree to be moved without reconfiguration. 98 | 99 | AC_DEFUN([AM_AUX_DIR_EXPAND], 100 | [dnl Rely on autoconf to set up CDPATH properly. 101 | AC_PREREQ([2.50])dnl 102 | # expand $ac_aux_dir to an absolute path 103 | am_aux_dir=`cd $ac_aux_dir && pwd` 104 | ]) 105 | 106 | # AM_CONDITIONAL -*- Autoconf -*- 107 | 108 | # Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006 109 | # Free Software Foundation, Inc. 110 | # 111 | # This file is free software; the Free Software Foundation 112 | # gives unlimited permission to copy and/or distribute it, 113 | # with or without modifications, as long as this notice is preserved. 114 | 115 | # serial 8 116 | 117 | # AM_CONDITIONAL(NAME, SHELL-CONDITION) 118 | # ------------------------------------- 119 | # Define a conditional. 120 | AC_DEFUN([AM_CONDITIONAL], 121 | [AC_PREREQ(2.52)dnl 122 | ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], 123 | [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl 124 | AC_SUBST([$1_TRUE])dnl 125 | AC_SUBST([$1_FALSE])dnl 126 | _AM_SUBST_NOTMAKE([$1_TRUE])dnl 127 | _AM_SUBST_NOTMAKE([$1_FALSE])dnl 128 | if $2; then 129 | $1_TRUE= 130 | $1_FALSE='#' 131 | else 132 | $1_TRUE='#' 133 | $1_FALSE= 134 | fi 135 | AC_CONFIG_COMMANDS_PRE( 136 | [if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then 137 | AC_MSG_ERROR([[conditional "$1" was never defined. 138 | Usually this means the macro was only invoked conditionally.]]) 139 | fi])]) 140 | 141 | # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 142 | # Free Software Foundation, Inc. 143 | # 144 | # This file is free software; the Free Software Foundation 145 | # gives unlimited permission to copy and/or distribute it, 146 | # with or without modifications, as long as this notice is preserved. 147 | 148 | # serial 9 149 | 150 | # There are a few dirty hacks below to avoid letting `AC_PROG_CC' be 151 | # written in clear, in which case automake, when reading aclocal.m4, 152 | # will think it sees a *use*, and therefore will trigger all it's 153 | # C support machinery. Also note that it means that autoscan, seeing 154 | # CC etc. in the Makefile, will ask for an AC_PROG_CC use... 155 | 156 | 157 | # _AM_DEPENDENCIES(NAME) 158 | # ---------------------- 159 | # See how the compiler implements dependency checking. 160 | # NAME is "CC", "CXX", "GCJ", or "OBJC". 161 | # We try a few techniques and use that to set a single cache variable. 162 | # 163 | # We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was 164 | # modified to invoke _AM_DEPENDENCIES(CC); we would have a circular 165 | # dependency, and given that the user is not expected to run this macro, 166 | # just rely on AC_PROG_CC. 167 | AC_DEFUN([_AM_DEPENDENCIES], 168 | [AC_REQUIRE([AM_SET_DEPDIR])dnl 169 | AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl 170 | AC_REQUIRE([AM_MAKE_INCLUDE])dnl 171 | AC_REQUIRE([AM_DEP_TRACK])dnl 172 | 173 | ifelse([$1], CC, [depcc="$CC" am_compiler_list=], 174 | [$1], CXX, [depcc="$CXX" am_compiler_list=], 175 | [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], 176 | [$1], UPC, [depcc="$UPC" am_compiler_list=], 177 | [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], 178 | [depcc="$$1" am_compiler_list=]) 179 | 180 | AC_CACHE_CHECK([dependency style of $depcc], 181 | [am_cv_$1_dependencies_compiler_type], 182 | [if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then 183 | # We make a subdir and do the tests there. Otherwise we can end up 184 | # making bogus files that we don't know about and never remove. For 185 | # instance it was reported that on HP-UX the gcc test will end up 186 | # making a dummy file named `D' -- because `-MD' means `put the output 187 | # in D'. 188 | mkdir conftest.dir 189 | # Copy depcomp to subdir because otherwise we won't find it if we're 190 | # using a relative directory. 191 | cp "$am_depcomp" conftest.dir 192 | cd conftest.dir 193 | # We will build objects and dependencies in a subdirectory because 194 | # it helps to detect inapplicable dependency modes. For instance 195 | # both Tru64's cc and ICC support -MD to output dependencies as a 196 | # side effect of compilation, but ICC will put the dependencies in 197 | # the current directory while Tru64 will put them in the object 198 | # directory. 199 | mkdir sub 200 | 201 | am_cv_$1_dependencies_compiler_type=none 202 | if test "$am_compiler_list" = ""; then 203 | am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` 204 | fi 205 | for depmode in $am_compiler_list; do 206 | # Setup a source with many dependencies, because some compilers 207 | # like to wrap large dependency lists on column 80 (with \), and 208 | # we should not choose a depcomp mode which is confused by this. 209 | # 210 | # We need to recreate these files for each test, as the compiler may 211 | # overwrite some of them when testing with obscure command lines. 212 | # This happens at least with the AIX C compiler. 213 | : > sub/conftest.c 214 | for i in 1 2 3 4 5 6; do 215 | echo '#include "conftst'$i'.h"' >> sub/conftest.c 216 | # Using `: > sub/conftst$i.h' creates only sub/conftst1.h with 217 | # Solaris 8's {/usr,}/bin/sh. 218 | touch sub/conftst$i.h 219 | done 220 | echo "${am__include} ${am__quote}sub/conftest.Po${am__quote}" > confmf 221 | 222 | case $depmode in 223 | nosideeffect) 224 | # after this tag, mechanisms are not by side-effect, so they'll 225 | # only be used when explicitly requested 226 | if test "x$enable_dependency_tracking" = xyes; then 227 | continue 228 | else 229 | break 230 | fi 231 | ;; 232 | none) break ;; 233 | esac 234 | # We check with `-c' and `-o' for the sake of the "dashmstdout" 235 | # mode. It turns out that the SunPro C++ compiler does not properly 236 | # handle `-M -o', and we need to detect this. 237 | if depmode=$depmode \ 238 | source=sub/conftest.c object=sub/conftest.${OBJEXT-o} \ 239 | depfile=sub/conftest.Po tmpdepfile=sub/conftest.TPo \ 240 | $SHELL ./depcomp $depcc -c -o sub/conftest.${OBJEXT-o} sub/conftest.c \ 241 | >/dev/null 2>conftest.err && 242 | grep sub/conftst1.h sub/conftest.Po > /dev/null 2>&1 && 243 | grep sub/conftst6.h sub/conftest.Po > /dev/null 2>&1 && 244 | grep sub/conftest.${OBJEXT-o} sub/conftest.Po > /dev/null 2>&1 && 245 | ${MAKE-make} -s -f confmf > /dev/null 2>&1; then 246 | # icc doesn't choke on unknown options, it will just issue warnings 247 | # or remarks (even with -Werror). So we grep stderr for any message 248 | # that says an option was ignored or not supported. 249 | # When given -MP, icc 7.0 and 7.1 complain thusly: 250 | # icc: Command line warning: ignoring option '-M'; no argument required 251 | # The diagnosis changed in icc 8.0: 252 | # icc: Command line remark: option '-MP' not supported 253 | if (grep 'ignoring option' conftest.err || 254 | grep 'not supported' conftest.err) >/dev/null 2>&1; then :; else 255 | am_cv_$1_dependencies_compiler_type=$depmode 256 | break 257 | fi 258 | fi 259 | done 260 | 261 | cd .. 262 | rm -rf conftest.dir 263 | else 264 | am_cv_$1_dependencies_compiler_type=none 265 | fi 266 | ]) 267 | AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) 268 | AM_CONDITIONAL([am__fastdep$1], [ 269 | test "x$enable_dependency_tracking" != xno \ 270 | && test "$am_cv_$1_dependencies_compiler_type" = gcc3]) 271 | ]) 272 | 273 | 274 | # AM_SET_DEPDIR 275 | # ------------- 276 | # Choose a directory name for dependency files. 277 | # This macro is AC_REQUIREd in _AM_DEPENDENCIES 278 | AC_DEFUN([AM_SET_DEPDIR], 279 | [AC_REQUIRE([AM_SET_LEADING_DOT])dnl 280 | AC_SUBST([DEPDIR], ["${am__leading_dot}deps"])dnl 281 | ]) 282 | 283 | 284 | # AM_DEP_TRACK 285 | # ------------ 286 | AC_DEFUN([AM_DEP_TRACK], 287 | [AC_ARG_ENABLE(dependency-tracking, 288 | [ --disable-dependency-tracking speeds up one-time build 289 | --enable-dependency-tracking do not reject slow dependency extractors]) 290 | if test "x$enable_dependency_tracking" != xno; then 291 | am_depcomp="$ac_aux_dir/depcomp" 292 | AMDEPBACKSLASH='\' 293 | fi 294 | AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) 295 | AC_SUBST([AMDEPBACKSLASH])dnl 296 | _AM_SUBST_NOTMAKE([AMDEPBACKSLASH])dnl 297 | ]) 298 | 299 | # Generate code to set up dependency tracking. -*- Autoconf -*- 300 | 301 | # Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 302 | # Free Software Foundation, Inc. 303 | # 304 | # This file is free software; the Free Software Foundation 305 | # gives unlimited permission to copy and/or distribute it, 306 | # with or without modifications, as long as this notice is preserved. 307 | 308 | #serial 3 309 | 310 | # _AM_OUTPUT_DEPENDENCY_COMMANDS 311 | # ------------------------------ 312 | AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], 313 | [for mf in $CONFIG_FILES; do 314 | # Strip MF so we end up with the name of the file. 315 | mf=`echo "$mf" | sed -e 's/:.*$//'` 316 | # Check whether this is an Automake generated Makefile or not. 317 | # We used to match only the files named `Makefile.in', but 318 | # some people rename them; so instead we look at the file content. 319 | # Grep'ing the first line is not enough: some people post-process 320 | # each Makefile.in and add a new line on top of each file to say so. 321 | # Grep'ing the whole file is not good either: AIX grep has a line 322 | # limit of 2048, but all sed's we know have understand at least 4000. 323 | if sed 10q "$mf" | grep '^#.*generated by automake' > /dev/null 2>&1; then 324 | dirpart=`AS_DIRNAME("$mf")` 325 | else 326 | continue 327 | fi 328 | # Extract the definition of DEPDIR, am__include, and am__quote 329 | # from the Makefile without running `make'. 330 | DEPDIR=`sed -n 's/^DEPDIR = //p' < "$mf"` 331 | test -z "$DEPDIR" && continue 332 | am__include=`sed -n 's/^am__include = //p' < "$mf"` 333 | test -z "am__include" && continue 334 | am__quote=`sed -n 's/^am__quote = //p' < "$mf"` 335 | # When using ansi2knr, U may be empty or an underscore; expand it 336 | U=`sed -n 's/^U = //p' < "$mf"` 337 | # Find all dependency output files, they are included files with 338 | # $(DEPDIR) in their names. We invoke sed twice because it is the 339 | # simplest approach to changing $(DEPDIR) to its actual value in the 340 | # expansion. 341 | for file in `sed -n " 342 | s/^$am__include $am__quote\(.*(DEPDIR).*\)$am__quote"'$/\1/p' <"$mf" | \ 343 | sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do 344 | # Make sure the directory exists. 345 | test -f "$dirpart/$file" && continue 346 | fdir=`AS_DIRNAME(["$file"])` 347 | AS_MKDIR_P([$dirpart/$fdir]) 348 | # echo "creating $dirpart/$file" 349 | echo '# dummy' > "$dirpart/$file" 350 | done 351 | done 352 | ])# _AM_OUTPUT_DEPENDENCY_COMMANDS 353 | 354 | 355 | # AM_OUTPUT_DEPENDENCY_COMMANDS 356 | # ----------------------------- 357 | # This macro should only be invoked once -- use via AC_REQUIRE. 358 | # 359 | # This code is only required when automatic dependency tracking 360 | # is enabled. FIXME. This creates each `.P' file that we will 361 | # need in order to bootstrap the dependency handling code. 362 | AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], 363 | [AC_CONFIG_COMMANDS([depfiles], 364 | [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], 365 | [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) 366 | ]) 367 | 368 | # Do all the work for Automake. -*- Autoconf -*- 369 | 370 | # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 371 | # 2005, 2006 Free Software Foundation, Inc. 372 | # 373 | # This file is free software; the Free Software Foundation 374 | # gives unlimited permission to copy and/or distribute it, 375 | # with or without modifications, as long as this notice is preserved. 376 | 377 | # serial 12 378 | 379 | # This macro actually does too much. Some checks are only needed if 380 | # your package does certain things. But this isn't really a big deal. 381 | 382 | # AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) 383 | # AM_INIT_AUTOMAKE([OPTIONS]) 384 | # ----------------------------------------------- 385 | # The call with PACKAGE and VERSION arguments is the old style 386 | # call (pre autoconf-2.50), which is being phased out. PACKAGE 387 | # and VERSION should now be passed to AC_INIT and removed from 388 | # the call to AM_INIT_AUTOMAKE. 389 | # We support both call styles for the transition. After 390 | # the next Automake release, Autoconf can make the AC_INIT 391 | # arguments mandatory, and then we can depend on a new Autoconf 392 | # release and drop the old call support. 393 | AC_DEFUN([AM_INIT_AUTOMAKE], 394 | [AC_PREREQ([2.60])dnl 395 | dnl Autoconf wants to disallow AM_ names. We explicitly allow 396 | dnl the ones we care about. 397 | m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl 398 | AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl 399 | AC_REQUIRE([AC_PROG_INSTALL])dnl 400 | if test "`cd $srcdir && pwd`" != "`pwd`"; then 401 | # Use -I$(srcdir) only when $(srcdir) != ., so that make's output 402 | # is not polluted with repeated "-I." 403 | AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl 404 | # test to see if srcdir already configured 405 | if test -f $srcdir/config.status; then 406 | AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) 407 | fi 408 | fi 409 | 410 | # test whether we have cygpath 411 | if test -z "$CYGPATH_W"; then 412 | if (cygpath --version) >/dev/null 2>/dev/null; then 413 | CYGPATH_W='cygpath -w' 414 | else 415 | CYGPATH_W=echo 416 | fi 417 | fi 418 | AC_SUBST([CYGPATH_W]) 419 | 420 | # Define the identity of the package. 421 | dnl Distinguish between old-style and new-style calls. 422 | m4_ifval([$2], 423 | [m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl 424 | AC_SUBST([PACKAGE], [$1])dnl 425 | AC_SUBST([VERSION], [$2])], 426 | [_AM_SET_OPTIONS([$1])dnl 427 | dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT. 428 | m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,, 429 | [m4_fatal([AC_INIT should be called with package and version arguments])])dnl 430 | AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl 431 | AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl 432 | 433 | _AM_IF_OPTION([no-define],, 434 | [AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) 435 | AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl 436 | 437 | # Some tools Automake needs. 438 | AC_REQUIRE([AM_SANITY_CHECK])dnl 439 | AC_REQUIRE([AC_ARG_PROGRAM])dnl 440 | AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) 441 | AM_MISSING_PROG(AUTOCONF, autoconf) 442 | AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) 443 | AM_MISSING_PROG(AUTOHEADER, autoheader) 444 | AM_MISSING_PROG(MAKEINFO, makeinfo) 445 | AM_PROG_INSTALL_SH 446 | AM_PROG_INSTALL_STRIP 447 | AC_REQUIRE([AM_PROG_MKDIR_P])dnl 448 | # We need awk for the "check" target. The system "awk" is bad on 449 | # some platforms. 450 | AC_REQUIRE([AC_PROG_AWK])dnl 451 | AC_REQUIRE([AC_PROG_MAKE_SET])dnl 452 | AC_REQUIRE([AM_SET_LEADING_DOT])dnl 453 | _AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])], 454 | [_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])], 455 | [_AM_PROG_TAR([v7])])]) 456 | _AM_IF_OPTION([no-dependencies],, 457 | [AC_PROVIDE_IFELSE([AC_PROG_CC], 458 | [_AM_DEPENDENCIES(CC)], 459 | [define([AC_PROG_CC], 460 | defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl 461 | AC_PROVIDE_IFELSE([AC_PROG_CXX], 462 | [_AM_DEPENDENCIES(CXX)], 463 | [define([AC_PROG_CXX], 464 | defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl 465 | AC_PROVIDE_IFELSE([AC_PROG_OBJC], 466 | [_AM_DEPENDENCIES(OBJC)], 467 | [define([AC_PROG_OBJC], 468 | defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl 469 | ]) 470 | ]) 471 | 472 | 473 | # When config.status generates a header, we must update the stamp-h file. 474 | # This file resides in the same directory as the config header 475 | # that is generated. The stamp files are numbered to have different names. 476 | 477 | # Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the 478 | # loop where config.status creates the headers, so we can generate 479 | # our stamp files there. 480 | AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK], 481 | [# Compute $1's index in $config_headers. 482 | _am_stamp_count=1 483 | for _am_header in $config_headers :; do 484 | case $_am_header in 485 | $1 | $1:* ) 486 | break ;; 487 | * ) 488 | _am_stamp_count=`expr $_am_stamp_count + 1` ;; 489 | esac 490 | done 491 | echo "timestamp for $1" >`AS_DIRNAME([$1])`/stamp-h[]$_am_stamp_count]) 492 | 493 | # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. 494 | # 495 | # This file is free software; the Free Software Foundation 496 | # gives unlimited permission to copy and/or distribute it, 497 | # with or without modifications, as long as this notice is preserved. 498 | 499 | # AM_PROG_INSTALL_SH 500 | # ------------------ 501 | # Define $install_sh. 502 | AC_DEFUN([AM_PROG_INSTALL_SH], 503 | [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl 504 | install_sh=${install_sh-"\$(SHELL) $am_aux_dir/install-sh"} 505 | AC_SUBST(install_sh)]) 506 | 507 | # Copyright (C) 2003, 2005 Free Software Foundation, Inc. 508 | # 509 | # This file is free software; the Free Software Foundation 510 | # gives unlimited permission to copy and/or distribute it, 511 | # with or without modifications, as long as this notice is preserved. 512 | 513 | # serial 2 514 | 515 | # Check whether the underlying file-system supports filenames 516 | # with a leading dot. For instance MS-DOS doesn't. 517 | AC_DEFUN([AM_SET_LEADING_DOT], 518 | [rm -rf .tst 2>/dev/null 519 | mkdir .tst 2>/dev/null 520 | if test -d .tst; then 521 | am__leading_dot=. 522 | else 523 | am__leading_dot=_ 524 | fi 525 | rmdir .tst 2>/dev/null 526 | AC_SUBST([am__leading_dot])]) 527 | 528 | # Check to see how 'make' treats includes. -*- Autoconf -*- 529 | 530 | # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. 531 | # 532 | # This file is free software; the Free Software Foundation 533 | # gives unlimited permission to copy and/or distribute it, 534 | # with or without modifications, as long as this notice is preserved. 535 | 536 | # serial 3 537 | 538 | # AM_MAKE_INCLUDE() 539 | # ----------------- 540 | # Check to see how make treats includes. 541 | AC_DEFUN([AM_MAKE_INCLUDE], 542 | [am_make=${MAKE-make} 543 | cat > confinc << 'END' 544 | am__doit: 545 | @echo done 546 | .PHONY: am__doit 547 | END 548 | # If we don't find an include directive, just comment out the code. 549 | AC_MSG_CHECKING([for style of include used by $am_make]) 550 | am__include="#" 551 | am__quote= 552 | _am_result=none 553 | # First try GNU make style include. 554 | echo "include confinc" > confmf 555 | # We grep out `Entering directory' and `Leaving directory' 556 | # messages which can occur if `w' ends up in MAKEFLAGS. 557 | # In particular we don't look at `^make:' because GNU make might 558 | # be invoked under some other name (usually "gmake"), in which 559 | # case it prints its new name instead of `make'. 560 | if test "`$am_make -s -f confmf 2> /dev/null | grep -v 'ing directory'`" = "done"; then 561 | am__include=include 562 | am__quote= 563 | _am_result=GNU 564 | fi 565 | # Now try BSD make style include. 566 | if test "$am__include" = "#"; then 567 | echo '.include "confinc"' > confmf 568 | if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then 569 | am__include=.include 570 | am__quote="\"" 571 | _am_result=BSD 572 | fi 573 | fi 574 | AC_SUBST([am__include]) 575 | AC_SUBST([am__quote]) 576 | AC_MSG_RESULT([$_am_result]) 577 | rm -f confinc confmf 578 | ]) 579 | 580 | # Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005 581 | # Free Software Foundation, Inc. 582 | # 583 | # This file is free software; the Free Software Foundation 584 | # gives unlimited permission to copy and/or distribute it, 585 | # with or without modifications, as long as this notice is preserved. 586 | 587 | # serial 5 588 | 589 | # AM_PROG_CC_C_O 590 | # -------------- 591 | # Like AC_PROG_CC_C_O, but changed for automake. 592 | AC_DEFUN([AM_PROG_CC_C_O], 593 | [AC_REQUIRE([AC_PROG_CC_C_O])dnl 594 | AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl 595 | AC_REQUIRE_AUX_FILE([compile])dnl 596 | # FIXME: we rely on the cache variable name because 597 | # there is no other way. 598 | set dummy $CC 599 | ac_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']` 600 | if eval "test \"`echo '$ac_cv_prog_cc_'${ac_cc}_c_o`\" != yes"; then 601 | # Losing compiler, so override with the script. 602 | # FIXME: It is wrong to rewrite CC. 603 | # But if we don't then we get into trouble of one sort or another. 604 | # A longer-term fix would be to have automake use am__CC in this case, 605 | # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)" 606 | CC="$am_aux_dir/compile $CC" 607 | fi 608 | dnl Make sure AC_PROG_CC is never called again, or it will override our 609 | dnl setting of CC. 610 | m4_define([AC_PROG_CC], 611 | [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])]) 612 | ]) 613 | 614 | # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*- 615 | 616 | # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005 617 | # Free Software Foundation, Inc. 618 | # 619 | # This file is free software; the Free Software Foundation 620 | # gives unlimited permission to copy and/or distribute it, 621 | # with or without modifications, as long as this notice is preserved. 622 | 623 | # serial 5 624 | 625 | # AM_MISSING_PROG(NAME, PROGRAM) 626 | # ------------------------------ 627 | AC_DEFUN([AM_MISSING_PROG], 628 | [AC_REQUIRE([AM_MISSING_HAS_RUN]) 629 | $1=${$1-"${am_missing_run}$2"} 630 | AC_SUBST($1)]) 631 | 632 | 633 | # AM_MISSING_HAS_RUN 634 | # ------------------ 635 | # Define MISSING if not defined so far and test if it supports --run. 636 | # If it does, set am_missing_run to use it, otherwise, to nothing. 637 | AC_DEFUN([AM_MISSING_HAS_RUN], 638 | [AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl 639 | AC_REQUIRE_AUX_FILE([missing])dnl 640 | test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" 641 | # Use eval to expand $SHELL 642 | if eval "$MISSING --run true"; then 643 | am_missing_run="$MISSING --run " 644 | else 645 | am_missing_run= 646 | AC_MSG_WARN([`missing' script is too old or missing]) 647 | fi 648 | ]) 649 | 650 | # Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 651 | # 652 | # This file is free software; the Free Software Foundation 653 | # gives unlimited permission to copy and/or distribute it, 654 | # with or without modifications, as long as this notice is preserved. 655 | 656 | # AM_PROG_MKDIR_P 657 | # --------------- 658 | # Check for `mkdir -p'. 659 | AC_DEFUN([AM_PROG_MKDIR_P], 660 | [AC_PREREQ([2.60])dnl 661 | AC_REQUIRE([AC_PROG_MKDIR_P])dnl 662 | dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P, 663 | dnl while keeping a definition of mkdir_p for backward compatibility. 664 | dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile. 665 | dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of 666 | dnl Makefile.ins that do not define MKDIR_P, so we do our own 667 | dnl adjustment using top_builddir (which is defined more often than 668 | dnl MKDIR_P). 669 | AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl 670 | case $mkdir_p in 671 | [[\\/$]]* | ?:[[\\/]]*) ;; 672 | */*) mkdir_p="\$(top_builddir)/$mkdir_p" ;; 673 | esac 674 | ]) 675 | 676 | # Helper functions for option handling. -*- Autoconf -*- 677 | 678 | # Copyright (C) 2001, 2002, 2003, 2005 Free Software Foundation, Inc. 679 | # 680 | # This file is free software; the Free Software Foundation 681 | # gives unlimited permission to copy and/or distribute it, 682 | # with or without modifications, as long as this notice is preserved. 683 | 684 | # serial 3 685 | 686 | # _AM_MANGLE_OPTION(NAME) 687 | # ----------------------- 688 | AC_DEFUN([_AM_MANGLE_OPTION], 689 | [[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) 690 | 691 | # _AM_SET_OPTION(NAME) 692 | # ------------------------------ 693 | # Set option NAME. Presently that only means defining a flag for this option. 694 | AC_DEFUN([_AM_SET_OPTION], 695 | [m4_define(_AM_MANGLE_OPTION([$1]), 1)]) 696 | 697 | # _AM_SET_OPTIONS(OPTIONS) 698 | # ---------------------------------- 699 | # OPTIONS is a space-separated list of Automake options. 700 | AC_DEFUN([_AM_SET_OPTIONS], 701 | [AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) 702 | 703 | # _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) 704 | # ------------------------------------------- 705 | # Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. 706 | AC_DEFUN([_AM_IF_OPTION], 707 | [m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) 708 | 709 | # Check to make sure that the build environment is sane. -*- Autoconf -*- 710 | 711 | # Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005 712 | # Free Software Foundation, Inc. 713 | # 714 | # This file is free software; the Free Software Foundation 715 | # gives unlimited permission to copy and/or distribute it, 716 | # with or without modifications, as long as this notice is preserved. 717 | 718 | # serial 4 719 | 720 | # AM_SANITY_CHECK 721 | # --------------- 722 | AC_DEFUN([AM_SANITY_CHECK], 723 | [AC_MSG_CHECKING([whether build environment is sane]) 724 | # Just in case 725 | sleep 1 726 | echo timestamp > conftest.file 727 | # Do `set' in a subshell so we don't clobber the current shell's 728 | # arguments. Must try -L first in case configure is actually a 729 | # symlink; some systems play weird games with the mod time of symlinks 730 | # (eg FreeBSD returns the mod time of the symlink's containing 731 | # directory). 732 | if ( 733 | set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` 734 | if test "$[*]" = "X"; then 735 | # -L didn't work. 736 | set X `ls -t $srcdir/configure conftest.file` 737 | fi 738 | rm -f conftest.file 739 | if test "$[*]" != "X $srcdir/configure conftest.file" \ 740 | && test "$[*]" != "X conftest.file $srcdir/configure"; then 741 | 742 | # If neither matched, then we have a broken ls. This can happen 743 | # if, for instance, CONFIG_SHELL is bash and it inherits a 744 | # broken ls alias from the environment. This has actually 745 | # happened. Such a system could not be considered "sane". 746 | AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken 747 | alias in your environment]) 748 | fi 749 | 750 | test "$[2]" = conftest.file 751 | ) 752 | then 753 | # Ok. 754 | : 755 | else 756 | AC_MSG_ERROR([newly created file is older than distributed files! 757 | Check your system clock]) 758 | fi 759 | AC_MSG_RESULT(yes)]) 760 | 761 | # Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc. 762 | # 763 | # This file is free software; the Free Software Foundation 764 | # gives unlimited permission to copy and/or distribute it, 765 | # with or without modifications, as long as this notice is preserved. 766 | 767 | # AM_PROG_INSTALL_STRIP 768 | # --------------------- 769 | # One issue with vendor `install' (even GNU) is that you can't 770 | # specify the program used to strip binaries. This is especially 771 | # annoying in cross-compiling environments, where the build's strip 772 | # is unlikely to handle the host's binaries. 773 | # Fortunately install-sh will honor a STRIPPROG variable, so we 774 | # always use install-sh in `make install-strip', and initialize 775 | # STRIPPROG with the value of the STRIP variable (set by the user). 776 | AC_DEFUN([AM_PROG_INSTALL_STRIP], 777 | [AC_REQUIRE([AM_PROG_INSTALL_SH])dnl 778 | # Installed binaries are usually stripped using `strip' when the user 779 | # run `make install-strip'. However `strip' might not be the right 780 | # tool to use in cross-compilation environments, therefore Automake 781 | # will honor the `STRIP' environment variable to overrule this program. 782 | dnl Don't test for $cross_compiling = yes, because it might be `maybe'. 783 | if test "$cross_compiling" != no; then 784 | AC_CHECK_TOOL([STRIP], [strip], :) 785 | fi 786 | INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s" 787 | AC_SUBST([INSTALL_STRIP_PROGRAM])]) 788 | 789 | # Copyright (C) 2006 Free Software Foundation, Inc. 790 | # 791 | # This file is free software; the Free Software Foundation 792 | # gives unlimited permission to copy and/or distribute it, 793 | # with or without modifications, as long as this notice is preserved. 794 | 795 | # _AM_SUBST_NOTMAKE(VARIABLE) 796 | # --------------------------- 797 | # Prevent Automake from outputing VARIABLE = @VARIABLE@ in Makefile.in. 798 | # This macro is traced by Automake. 799 | AC_DEFUN([_AM_SUBST_NOTMAKE]) 800 | 801 | # Check how to create a tarball. -*- Autoconf -*- 802 | 803 | # Copyright (C) 2004, 2005 Free Software Foundation, Inc. 804 | # 805 | # This file is free software; the Free Software Foundation 806 | # gives unlimited permission to copy and/or distribute it, 807 | # with or without modifications, as long as this notice is preserved. 808 | 809 | # serial 2 810 | 811 | # _AM_PROG_TAR(FORMAT) 812 | # -------------------- 813 | # Check how to create a tarball in format FORMAT. 814 | # FORMAT should be one of `v7', `ustar', or `pax'. 815 | # 816 | # Substitute a variable $(am__tar) that is a command 817 | # writing to stdout a FORMAT-tarball containing the directory 818 | # $tardir. 819 | # tardir=directory && $(am__tar) > result.tar 820 | # 821 | # Substitute a variable $(am__untar) that extract such 822 | # a tarball read from stdin. 823 | # $(am__untar) < result.tar 824 | AC_DEFUN([_AM_PROG_TAR], 825 | [# Always define AMTAR for backward compatibility. 826 | AM_MISSING_PROG([AMTAR], [tar]) 827 | m4_if([$1], [v7], 828 | [am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'], 829 | [m4_case([$1], [ustar],, [pax],, 830 | [m4_fatal([Unknown tar format])]) 831 | AC_MSG_CHECKING([how to create a $1 tar archive]) 832 | # Loop over all known methods to create a tar archive until one works. 833 | _am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none' 834 | _am_tools=${am_cv_prog_tar_$1-$_am_tools} 835 | # Do not fold the above two line into one, because Tru64 sh and 836 | # Solaris sh will not grok spaces in the rhs of `-'. 837 | for _am_tool in $_am_tools 838 | do 839 | case $_am_tool in 840 | gnutar) 841 | for _am_tar in tar gnutar gtar; 842 | do 843 | AM_RUN_LOG([$_am_tar --version]) && break 844 | done 845 | am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"' 846 | am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"' 847 | am__untar="$_am_tar -xf -" 848 | ;; 849 | plaintar) 850 | # Must skip GNU tar: if it does not support --format= it doesn't create 851 | # ustar tarball either. 852 | (tar --version) >/dev/null 2>&1 && continue 853 | am__tar='tar chf - "$$tardir"' 854 | am__tar_='tar chf - "$tardir"' 855 | am__untar='tar xf -' 856 | ;; 857 | pax) 858 | am__tar='pax -L -x $1 -w "$$tardir"' 859 | am__tar_='pax -L -x $1 -w "$tardir"' 860 | am__untar='pax -r' 861 | ;; 862 | cpio) 863 | am__tar='find "$$tardir" -print | cpio -o -H $1 -L' 864 | am__tar_='find "$tardir" -print | cpio -o -H $1 -L' 865 | am__untar='cpio -i -H $1 -d' 866 | ;; 867 | none) 868 | am__tar=false 869 | am__tar_=false 870 | am__untar=false 871 | ;; 872 | esac 873 | 874 | # If the value was cached, stop now. We just wanted to have am__tar 875 | # and am__untar set. 876 | test -n "${am_cv_prog_tar_$1}" && break 877 | 878 | # tar/untar a dummy directory, and stop if the command works 879 | rm -rf conftest.dir 880 | mkdir conftest.dir 881 | echo GrepMe > conftest.dir/file 882 | AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar]) 883 | rm -rf conftest.dir 884 | if test -s conftest.tar; then 885 | AM_RUN_LOG([$am__untar /dev/null 2>&1 && break 887 | fi 888 | done 889 | rm -rf conftest.dir 890 | 891 | AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool]) 892 | AC_MSG_RESULT([$am_cv_prog_tar_$1])]) 893 | AC_SUBST([am__tar]) 894 | AC_SUBST([am__untar]) 895 | ]) # _AM_PROG_TAR 896 | 897 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | 4 | echo "autoreconf --install" 5 | autoreconf --install 6 | -------------------------------------------------------------------------------- /bdb.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | /* 3 | * MemcacheQ - Simple Queue Service over Memcache 4 | * 5 | * http://memcacheq.googlecode.com 6 | * 7 | * The source code of MemcacheQ is most based on MemcachDB: 8 | * 9 | * http://memcachedb.googlecode.com 10 | * 11 | * Copyright 2008 Steve Chu. All rights reserved. 12 | * 13 | * Use and distribution licensed under the BSD license. See 14 | * the LICENSE file for full text. 15 | * 16 | * Authors: 17 | * Steve Chu 18 | * 19 | */ 20 | 21 | #include "memcacheq.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #define CHECK_DB_RET(ret) \ 35 | if (0!=ret) goto dberr 36 | 37 | static unsigned int hashfromkey(void *k); 38 | static int equalkeys(void *k1, void *k2); 39 | static void open_exsited_queue_db(DB_TXN *txn, char *qn, qstats_t *qs); 40 | static void dump_qstats_to_db(void); 41 | static void *bdb_checkpoint_thread __P((void *)); 42 | static void *bdb_mempool_trickle_thread __P((void *)); 43 | static void *bdb_deadlock_detect_thread __P((void *)); 44 | static void *bdb_qstats_dump_thread __P((void *)); 45 | static void bdb_err_callback(const DB_ENV *dbenv, const char *errpfx, const char *msg); 46 | static void bdb_msg_callback(const DB_ENV *dbenv, const char *msg); 47 | 48 | static unsigned int hashfromkey(void *k) { 49 | return murmurhash2(k, strlen(k), 0); 50 | } 51 | 52 | static int equalkeys(void *k1, void *k2) { 53 | return (0 == strcmp(k1,k2)); 54 | } 55 | 56 | static struct hashtable *qlist_htp; 57 | static pthread_rwlock_t qlist_ht_lock; 58 | static DB *qlist_dbp = NULL; 59 | 60 | void qlist_ht_init(void) { 61 | pthread_rwlock_init(&qlist_ht_lock, NULL); 62 | qlist_htp = create_hashtable(64, hashfromkey, equalkeys); 63 | if (NULL == qlist_htp) { 64 | fprintf(stderr, "create_hashtable fail\n"); 65 | exit(EXIT_FAILURE); 66 | } 67 | } 68 | 69 | void qlist_ht_close(void) { 70 | hashtable_destroy(qlist_htp, 1); 71 | pthread_rwlock_destroy(&qlist_ht_lock); 72 | } 73 | 74 | void bdb_settings_init(void){ 75 | bdb_settings.env_home = DBHOME; 76 | bdb_settings.cache_size = 64 * 1024 * 1024; /* default is 64MB */ 77 | bdb_settings.txn_lg_bsize = 32 * 1024; /* default is 32KB */ 78 | 79 | bdb_settings.re_len = 1024; 80 | bdb_settings.q_extentsize = 16 * 1024; // 64MB extent file each 81 | 82 | bdb_settings.page_size = 4096; /* default is 4K */ 83 | bdb_settings.txn_nosync = 0; /* default DB_TXN_NOSYNC is off */ 84 | bdb_settings.log_auto_remove = 0; 85 | bdb_settings.deadlock_detect_val = 100 * 1000; /* default is 100 millisecond */ 86 | bdb_settings.checkpoint_val = 60 * 5; /* seconds */ 87 | bdb_settings.mempool_trickle_val = 30; /* seconds */ 88 | bdb_settings.mempool_trickle_percent = 60; 89 | bdb_settings.qstats_dump_val = 30; /* seconds */ 90 | } 91 | 92 | void bdb_env_init(void){ 93 | int ret; 94 | u_int32_t env_flags = DB_CREATE 95 | | DB_INIT_LOCK 96 | | DB_THREAD 97 | | DB_INIT_MPOOL 98 | | DB_INIT_LOG 99 | | DB_INIT_TXN 100 | | DB_RECOVER; 101 | /* db env init */ 102 | if ((ret = db_env_create(&envp, 0)) != 0) { 103 | fprintf(stderr, "db_env_create: %s\n", db_strerror(ret)); 104 | exit(EXIT_FAILURE); 105 | } 106 | 107 | /* set err&msg display */ 108 | envp->set_errpfx(envp, PACKAGE); 109 | envp->set_errcall(envp, bdb_err_callback); 110 | envp->set_msgcall(envp, bdb_msg_callback); 111 | 112 | /* set MPOOL size */ 113 | envp->set_cachesize(envp, 0, bdb_settings.cache_size, 0); 114 | 115 | /* set DB_TXN_NOSYNC flag */ 116 | if (bdb_settings.txn_nosync){ 117 | envp->set_flags(envp, DB_TXN_NOSYNC, 1); 118 | } 119 | /* Auto remove log */ 120 | if (bdb_settings.log_auto_remove) { 121 | envp->log_set_config(envp, DB_LOG_AUTO_REMOVE, 1); 122 | } 123 | 124 | /* set locking */ 125 | envp->set_lk_max_lockers(envp, 40000); 126 | envp->set_lk_max_locks(envp, 40000); 127 | envp->set_lk_max_objects(envp, 40000); 128 | 129 | /* at least max active transactions */ 130 | envp->set_tx_max(envp, 40000); 131 | 132 | /* set transaction log buffer */ 133 | envp->set_lg_bsize(envp, bdb_settings.txn_lg_bsize); 134 | 135 | /* if no home dir existed, we create it */ 136 | if (0 != access(bdb_settings.env_home, F_OK)) { 137 | if (0 != mkdir(bdb_settings.env_home, 0750)) { 138 | fprintf(stderr, "mkdir env_home error:[%s]\n", bdb_settings.env_home); 139 | exit(EXIT_FAILURE); 140 | } 141 | } 142 | 143 | if ((ret = envp->open(envp, bdb_settings.env_home, env_flags, 0)) != 0) { 144 | fprintf(stderr, "envp->open: %s\n", db_strerror(ret)); 145 | exit(EXIT_FAILURE); 146 | } 147 | } 148 | 149 | void bdb_env_close(void){ 150 | int ret = 0; 151 | if (envp != NULL) { 152 | ret = envp->close(envp, 0); 153 | if (0 != ret){ 154 | fprintf(stderr, "envp->close: %s\n", db_strerror(ret)); 155 | }else{ 156 | envp = NULL; 157 | fprintf(stderr, "envp->close: OK\n"); 158 | } 159 | } 160 | } 161 | 162 | void bdb_qlist_db_open(void){ 163 | int ret; 164 | DBC *cursorp = NULL; 165 | DB_TXN *txnp = NULL; 166 | 167 | /* Create queue.list db handle */ 168 | ret = db_create(&qlist_dbp, envp, 0); 169 | CHECK_DB_RET(ret); 170 | 171 | /* Open and Iterate */ 172 | ret = envp->txn_begin(envp, NULL, &txnp, 0); 173 | CHECK_DB_RET(ret); 174 | ret = qlist_dbp->open(qlist_dbp, txnp, "queue.list", NULL, DB_BTREE, DB_CREATE, 0664); 175 | CHECK_DB_RET(ret); 176 | ret = qlist_dbp->cursor(qlist_dbp, txnp, &cursorp, 0); 177 | CHECK_DB_RET(ret); 178 | DBT dbkey, dbdata; 179 | char qname[512]; 180 | qstats_t qs; 181 | BDB_CLEANUP_DBT(); 182 | memset(qname, 0, 512); 183 | memset(&qs, 0, sizeof(qs)); 184 | dbkey.data = (void *)qname; 185 | dbkey.ulen = 512; 186 | dbkey.flags = DB_DBT_USERMEM; 187 | dbdata.data = (void *)&qs; 188 | dbdata.ulen = sizeof(qs); 189 | dbdata.flags = DB_DBT_USERMEM; 190 | 191 | while ((ret = cursorp->get(cursorp, &dbkey, &dbdata, DB_NEXT)) == 0) { 192 | open_exsited_queue_db(txnp, qname, &qs); 193 | } 194 | if (ret != DB_NOTFOUND) { 195 | goto dberr; 196 | } 197 | 198 | ret = cursorp->close(cursorp); 199 | CHECK_DB_RET(ret); 200 | 201 | ret = txnp->commit(txnp, 0); 202 | CHECK_DB_RET(ret); 203 | return; 204 | 205 | dberr: 206 | if (cursorp != NULL){ 207 | cursorp->close(cursorp); 208 | } 209 | if (txnp != NULL){ 210 | txnp->abort(txnp); 211 | } 212 | fprintf(stderr, "bdb_qlist_db_open: %s\n", db_strerror(ret)); 213 | exit(EXIT_FAILURE); 214 | } 215 | 216 | static void open_exsited_queue_db(DB_TXN *txnp, char *queue_name, qstats_t *qsp){ 217 | int ret; 218 | 219 | char *k = strdup(queue_name); 220 | assert(k != NULL); 221 | queue_t *q = (queue_t *)calloc(1, sizeof(queue_t)); 222 | assert(q != NULL); 223 | 224 | /* init hash_key and hash_value */ 225 | q->dbp = NULL; 226 | q->set_hits = q->old_set_hits = qsp->set_hits; 227 | q->get_hits = q->old_get_hits = qsp->get_hits; 228 | pthread_mutex_init(&(q->lock), NULL); 229 | 230 | ret = db_create(&(q->dbp), envp, 0); 231 | CHECK_DB_RET(ret); 232 | ret = q->dbp->open(q->dbp, txnp, queue_name, NULL, DB_QUEUE, DB_CREATE, 0664); 233 | CHECK_DB_RET(ret); 234 | 235 | int result = hashtable_insert(qlist_htp, (void *)k, (void *)q); 236 | assert(result != 0); 237 | return; 238 | 239 | dberr: 240 | fprintf(stderr, "open_exsited_queue_db: %s\n", db_strerror(ret)); 241 | exit(EXIT_FAILURE); 242 | } 243 | 244 | void bdb_qlist_db_close(void){ 245 | dump_qstats_to_db(); 246 | 247 | struct hashtable_itr *itr = NULL; 248 | queue_t *q; 249 | itr = hashtable_iterator(qlist_htp); 250 | assert(itr != NULL); 251 | if (hashtable_count(qlist_htp) > 0) 252 | { 253 | do { 254 | q = hashtable_iterator_value(itr); 255 | q->dbp->close(q->dbp, 0); 256 | pthread_mutex_destroy(&(q->lock)); 257 | } while (hashtable_iterator_advance(itr)); 258 | } 259 | free(itr); 260 | if (qlist_dbp != NULL) { 261 | qlist_dbp->close(qlist_dbp, 0); 262 | } 263 | fprintf(stderr, "qlist_dbp->close: OK\n"); 264 | } 265 | 266 | int bdb_create_queue(char *queue_name) { 267 | char *k = strdup(queue_name); 268 | assert(k != NULL); 269 | queue_t *q = (queue_t *)calloc(1, sizeof(queue_t)); 270 | assert(q != NULL); 271 | 272 | q->dbp = NULL; 273 | q->set_hits = q->old_set_hits = 0; 274 | q->get_hits = q->old_get_hits = 0; 275 | pthread_mutex_init(&(q->lock), NULL); 276 | 277 | int ret; 278 | DB_TXN *txnp = NULL; 279 | ret = db_create(&(q->dbp), envp, 0); 280 | CHECK_DB_RET(ret); 281 | 282 | if (bdb_settings.q_extentsize != 0){ 283 | ret = q->dbp->set_q_extentsize(q->dbp, bdb_settings.q_extentsize); 284 | CHECK_DB_RET(ret); 285 | } 286 | ret = q->dbp->set_re_len(q->dbp, bdb_settings.re_len); 287 | CHECK_DB_RET(ret); 288 | ret = q->dbp->set_pagesize(q->dbp, bdb_settings.page_size); 289 | CHECK_DB_RET(ret); 290 | 291 | ret = envp->txn_begin(envp, NULL, &txnp, 0); 292 | CHECK_DB_RET(ret); 293 | ret = q->dbp->open(q->dbp, txnp, queue_name, NULL, DB_QUEUE, DB_CREATE, 0664); 294 | CHECK_DB_RET(ret); 295 | 296 | DBT dbkey,dbdata; 297 | qstats_t qs; 298 | BDB_CLEANUP_DBT(); 299 | memset(&qs, 0, sizeof(qs)); 300 | dbkey.data = (void *)queue_name; 301 | dbkey.size = strlen(queue_name)+1; 302 | dbdata.data = (void *)&qs; 303 | dbdata.size = sizeof(qstats_t); 304 | ret = qlist_dbp->put(qlist_dbp, txnp, &dbkey, &dbdata, 0); 305 | CHECK_DB_RET(ret); 306 | ret = txnp->commit(txnp, 0); 307 | CHECK_DB_RET(ret); 308 | int result = hashtable_insert(qlist_htp, (void *)k, (void *)q); 309 | assert(result != 0); 310 | return 0; 311 | dberr: 312 | if (txnp != NULL){ 313 | txnp->abort(txnp); 314 | } 315 | fprintf(stderr, "bdb_create_queue: %s %s\n", queue_name, db_strerror(ret)); 316 | return -1; 317 | } 318 | 319 | int bdb_delete_queue(char *queue_name){ 320 | pthread_rwlock_wrlock(&qlist_ht_lock); 321 | queue_t *q = hashtable_search(qlist_htp, (void *)queue_name); 322 | /* NOT FOUND */ 323 | if (q == NULL) { 324 | pthread_rwlock_unlock(&qlist_ht_lock); 325 | return 1; 326 | } 327 | /* Found, just close and remove it. */ 328 | q->dbp->close(q->dbp, 0); 329 | pthread_mutex_destroy(&(q->lock)); 330 | q = hashtable_remove(qlist_htp, (void *)queue_name); 331 | assert(NULL != q); 332 | free(q); 333 | 334 | int ret; 335 | DB_TXN *txnp = NULL; 336 | ret = envp->txn_begin(envp, NULL, &txnp, 0); 337 | CHECK_DB_RET(ret); 338 | ret = envp->dbremove(envp, txnp, queue_name, NULL, 0); 339 | CHECK_DB_RET(ret); 340 | DBT dbkey; 341 | memset(&dbkey, 0, sizeof(dbkey)); 342 | dbkey.data = (void *)queue_name; 343 | dbkey.size = strlen(queue_name) + 1; 344 | ret = qlist_dbp->del(qlist_dbp, txnp, &dbkey, 0); 345 | CHECK_DB_RET(ret); 346 | ret = txnp->commit(txnp, 0); 347 | CHECK_DB_RET(ret); 348 | pthread_rwlock_unlock(&qlist_ht_lock); 349 | return 0; 350 | dberr: 351 | if (txnp != NULL){ 352 | txnp->abort(txnp); 353 | } 354 | fprintf(stderr, "bdb_delete_queue: %s %s\n", queue_name, db_strerror(ret)); 355 | pthread_rwlock_unlock(&qlist_ht_lock); 356 | return -1; 357 | } 358 | 359 | static void dump_qstats_to_db(void) { 360 | /* qstats hashtable */ 361 | char *kk; 362 | qstats_t *s; 363 | struct hashtable *qstats_htp = NULL; 364 | qstats_htp = create_hashtable(64, hashfromkey, equalkeys); 365 | assert(qstats_htp != NULL); 366 | 367 | /* cp hashtable to stats table, this is very fast in-memory */ 368 | pthread_rwlock_rdlock(&qlist_ht_lock); 369 | char *k; 370 | queue_t *q; 371 | int result; 372 | struct hashtable_itr *itr = NULL; 373 | itr = hashtable_iterator(qlist_htp); 374 | assert(itr != NULL); 375 | if (hashtable_count(qlist_htp) > 0) 376 | { 377 | do { 378 | k = hashtable_iterator_key(itr); 379 | q = hashtable_iterator_value(itr); 380 | pthread_mutex_lock(&(q->lock)); 381 | if (q->old_set_hits == q->set_hits && 382 | q->old_get_hits == q->get_hits) { 383 | pthread_mutex_unlock(&(q->lock)); 384 | continue; 385 | } 386 | q->old_set_hits = q->set_hits; 387 | q->old_get_hits = q->get_hits; 388 | pthread_mutex_unlock(&(q->lock)); 389 | kk = strdup(k); 390 | assert(kk); 391 | s = calloc(1, sizeof(qstats_t)); 392 | assert(s); 393 | s->set_hits = q->old_set_hits; 394 | s->get_hits = q->old_get_hits; 395 | result = hashtable_insert(qstats_htp, (void *)kk, (void *)s); 396 | assert(result != 0); 397 | } while (hashtable_iterator_advance(itr)); 398 | } 399 | free(itr); 400 | itr = NULL; 401 | pthread_rwlock_unlock(&qlist_ht_lock); 402 | 403 | /* dump stats hashtable to db */ 404 | DBT dbkey, dbdata; 405 | int ret; 406 | DB_TXN *txnp = NULL; 407 | ret = envp->txn_begin(envp, NULL, &txnp, 0); 408 | CHECK_DB_RET(ret); 409 | itr = hashtable_iterator(qstats_htp); 410 | assert(itr != NULL); 411 | if (hashtable_count(qstats_htp) > 0) 412 | { 413 | do { 414 | kk = hashtable_iterator_key(itr); 415 | s = hashtable_iterator_value(itr); 416 | BDB_CLEANUP_DBT(); 417 | dbkey.data = (void *)kk; 418 | dbkey.size = strlen(kk) + 1; 419 | dbdata.data = (void *)s; 420 | dbdata.size = sizeof(qstats_t); 421 | ret = qlist_dbp->put(qlist_dbp, txnp, &dbkey, &dbdata, 0); 422 | CHECK_DB_RET(ret); 423 | fprintf(stderr, "dump stats[%s], set_hits: %lld, get_hits: %lld \n", 424 | kk, s->set_hits, s->get_hits); 425 | } while (hashtable_iterator_advance(itr)); 426 | } 427 | free(itr); 428 | itr = NULL; 429 | ret = txnp->commit(txnp, 0); 430 | CHECK_DB_RET(ret); 431 | 432 | hashtable_destroy(qstats_htp, 1); 433 | qstats_htp = NULL; 434 | return; 435 | dberr: 436 | if(itr != NULL) { 437 | free(itr); 438 | } 439 | if (qstats_htp != NULL) { 440 | hashtable_destroy(qstats_htp, 1); 441 | } 442 | if (txnp != NULL){ 443 | txnp->abort(txnp); 444 | } 445 | if (settings.verbose > 1) { 446 | fprintf(stderr, "dump_qstats_to_db: %s\n", db_strerror(ret)); 447 | } 448 | } 449 | 450 | void print_queue_stats(char *temp, int len_limit) { 451 | char *pos = temp; 452 | int remains = len_limit - 3; 453 | int res; 454 | int64_t set_hits,get_hits; 455 | pthread_rwlock_rdlock(&qlist_ht_lock); 456 | char *k; 457 | queue_t *q; 458 | struct hashtable_itr *itr = NULL; 459 | itr = hashtable_iterator(qlist_htp); 460 | assert(itr != NULL); 461 | if (hashtable_count(qlist_htp) > 0) 462 | { 463 | do { 464 | k = hashtable_iterator_key(itr); 465 | q = hashtable_iterator_value(itr); 466 | pthread_mutex_lock(&(q->lock)); 467 | set_hits = q->set_hits; 468 | get_hits = q->get_hits; 469 | pthread_mutex_unlock(&(q->lock)); 470 | if (remains > strlen(k) + 50) { 471 | res = sprintf(pos, "STAT %s %lld/%lld\r\n", k, set_hits, get_hits); 472 | remains -= res; 473 | pos += res; 474 | } else { 475 | break; 476 | } 477 | } while (hashtable_iterator_advance(itr)); 478 | } 479 | free(itr); 480 | pthread_rwlock_unlock(&qlist_ht_lock); 481 | sprintf(pos, "END"); 482 | return; 483 | } 484 | 485 | 486 | /* if return item is not NULL, free by caller */ 487 | item *bdb_get(char *key){ 488 | pthread_rwlock_rdlock(&qlist_ht_lock); 489 | item *it = NULL; 490 | DB_TXN *txnp = NULL; 491 | int ret; 492 | 493 | queue_t *q = (queue_t *)hashtable_search(qlist_htp, (void *)key); 494 | /* queue not exsited */ 495 | if (q == NULL) { 496 | pthread_rwlock_unlock(&qlist_ht_lock); 497 | return NULL; 498 | } else { 499 | DBT dbkey, dbdata; 500 | db_recno_t recno; 501 | 502 | /* first, alloc a fixed size */ 503 | it = item_alloc2(); 504 | if (it == 0) { 505 | pthread_rwlock_unlock(&qlist_ht_lock); 506 | return NULL; 507 | } 508 | 509 | BDB_CLEANUP_DBT(); 510 | dbkey.data = &recno; 511 | dbkey.ulen = sizeof(recno); 512 | dbkey.flags = DB_DBT_USERMEM; 513 | dbdata.ulen = bdb_settings.re_len; 514 | dbdata.data = it; 515 | dbdata.flags = DB_DBT_USERMEM; 516 | 517 | ret = envp->txn_begin(envp, NULL, &txnp, 0); 518 | CHECK_DB_RET(ret); 519 | ret = q->dbp->get(q->dbp, txnp, &dbkey, &dbdata, DB_CONSUME); 520 | CHECK_DB_RET(ret); 521 | ret = txnp->commit(txnp, 0); 522 | CHECK_DB_RET(ret); 523 | pthread_mutex_lock(&(q->lock)); 524 | (q->get_hits)++; 525 | pthread_mutex_unlock(&(q->lock)); 526 | } 527 | pthread_rwlock_unlock(&qlist_ht_lock); 528 | return it; 529 | dberr: 530 | item_free(it); 531 | it = NULL; 532 | if (txnp != NULL){ 533 | txnp->abort(txnp); 534 | } 535 | if (settings.verbose > 1) { 536 | fprintf(stderr, "bdb_get: %s\n", db_strerror(ret)); 537 | } 538 | pthread_rwlock_unlock(&qlist_ht_lock); 539 | return NULL; 540 | } 541 | 542 | /* 0 for Success 543 | -1 for SERVER_ERROR 544 | */ 545 | int bdb_set(char *key, item *it){ 546 | pthread_rwlock_rdlock(&qlist_ht_lock); 547 | queue_t *q = (queue_t *)hashtable_search(qlist_htp, (void *)key); 548 | DB_TXN *txnp = NULL; 549 | int ret; 550 | 551 | if (NULL == q) { 552 | pthread_rwlock_unlock(&qlist_ht_lock); 553 | /* switch to write lock */ 554 | pthread_rwlock_wrlock(&qlist_ht_lock); 555 | ret = bdb_create_queue(key); 556 | if (0 != ret){ 557 | return -1; 558 | } 559 | /* search again */ 560 | q = (queue_t *)hashtable_search(qlist_htp, (void *)key); 561 | } 562 | 563 | if (NULL != q) { 564 | db_recno_t recno; 565 | DBT dbkey, dbdata; 566 | BDB_CLEANUP_DBT(); 567 | dbkey.data = &recno; 568 | dbkey.ulen = sizeof(recno); 569 | dbkey.flags = DB_DBT_USERMEM; 570 | dbdata.data = it; 571 | dbdata.size = ITEM_ntotal(it); 572 | ret = envp->txn_begin(envp, NULL, &txnp, 0); 573 | CHECK_DB_RET(ret); 574 | ret = q->dbp->put(q->dbp, txnp, &dbkey, &dbdata, DB_APPEND); 575 | CHECK_DB_RET(ret); 576 | ret = txnp->commit(txnp, 0); 577 | CHECK_DB_RET(ret); 578 | pthread_mutex_lock(&(q->lock)); 579 | (q->set_hits)++; 580 | pthread_mutex_unlock(&(q->lock)); 581 | } 582 | pthread_rwlock_unlock(&qlist_ht_lock); 583 | return 0; 584 | dberr: 585 | if (txnp != NULL){ 586 | txnp->abort(txnp); 587 | } 588 | if (settings.verbose > 1) { 589 | fprintf(stderr, "bdb_set: %s\n", db_strerror(ret)); 590 | } 591 | pthread_rwlock_unlock(&qlist_ht_lock); 592 | return -1; 593 | } 594 | 595 | void start_checkpoint_thread(void){ 596 | pthread_t tid; 597 | if (bdb_settings.checkpoint_val > 0){ 598 | /* Start a checkpoint thread. */ 599 | if ((errno = pthread_create( 600 | &tid, NULL, bdb_checkpoint_thread, (void *)envp)) != 0) { 601 | fprintf(stderr, 602 | "failed spawning checkpoint thread: %s\n", 603 | strerror(errno)); 604 | exit(EXIT_FAILURE); 605 | } 606 | } 607 | } 608 | 609 | void start_mempool_trickle_thread(void){ 610 | pthread_t tid; 611 | if (bdb_settings.mempool_trickle_val > 0){ 612 | /* Start a memp_trickle thread. */ 613 | if ((errno = pthread_create( 614 | &tid, NULL, bdb_mempool_trickle_thread, (void *)envp)) != 0) { 615 | fprintf(stderr, 616 | "failed spawning memp_trickle thread: %s\n", 617 | strerror(errno)); 618 | exit(EXIT_FAILURE); 619 | } 620 | } 621 | } 622 | 623 | void start_deadlock_detect_thread(void){ 624 | pthread_t tid; 625 | if (bdb_settings.deadlock_detect_val > 0){ 626 | /* Start a deadlock detecting thread. */ 627 | if ((errno = pthread_create( 628 | &tid, NULL, bdb_deadlock_detect_thread, (void *)envp)) != 0) { 629 | fprintf(stderr, 630 | "failed spawning deadlock thread: %s\n", 631 | strerror(errno)); 632 | exit(EXIT_FAILURE); 633 | } 634 | } 635 | } 636 | 637 | void start_qstats_dump_thread(void){ 638 | pthread_t tid; 639 | if (bdb_settings.qstats_dump_val > 0){ 640 | /* Start a queue stats dump thread. */ 641 | if ((errno = pthread_create( 642 | &tid, NULL, bdb_qstats_dump_thread, (void *)envp)) != 0) { 643 | fprintf(stderr, 644 | "failed spawning qstats dump thread: %s\n", 645 | strerror(errno)); 646 | exit(EXIT_FAILURE); 647 | } 648 | } 649 | } 650 | 651 | static void *bdb_checkpoint_thread(void *arg){ 652 | DB_ENV *dbenv; 653 | int ret; 654 | dbenv = arg; 655 | for (;; sleep(bdb_settings.checkpoint_val)) { 656 | if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, 0)) != 0) { 657 | dbenv->err(dbenv, ret, "checkpoint thread"); 658 | } 659 | dbenv->errx(dbenv, "checkpoint thread: a txn_checkpoint is done"); 660 | } 661 | return (NULL); 662 | } 663 | 664 | static void *bdb_mempool_trickle_thread(void *arg){ 665 | DB_ENV *dbenv; 666 | int ret, nwrotep; 667 | dbenv = arg; 668 | for (;; sleep(bdb_settings.mempool_trickle_val)) { 669 | if ((ret = dbenv->memp_trickle(dbenv, bdb_settings.mempool_trickle_percent, &nwrotep)) != 0) { 670 | dbenv->err(dbenv, ret, "mempool_trickle thread"); 671 | } 672 | dbenv->errx(dbenv, "mempool_trickle thread: writing %d dirty pages", nwrotep); 673 | } 674 | return (NULL); 675 | } 676 | 677 | static void *bdb_deadlock_detect_thread(void *arg){ 678 | DB_ENV *dbenv; 679 | struct timeval t; 680 | dbenv = arg; 681 | while (!daemon_quit) { 682 | t.tv_sec = 0; 683 | t.tv_usec = bdb_settings.deadlock_detect_val; 684 | (void)dbenv->lock_detect(dbenv, 0, DB_LOCK_YOUNGEST, NULL); 685 | /* select is a more accurate sleep timer */ 686 | (void)select(0, NULL, NULL, NULL, &t); 687 | } 688 | return (NULL); 689 | } 690 | 691 | static void *bdb_qstats_dump_thread(void *arg){ 692 | DB_ENV *dbenv; 693 | int ret; 694 | dbenv = arg; 695 | for (;; sleep(bdb_settings.qstats_dump_val)) { 696 | dump_qstats_to_db(); 697 | dbenv->errx(dbenv, "qstats dump thread: a qstats is dump."); 698 | } 699 | return (NULL); 700 | } 701 | 702 | static void bdb_err_callback(const DB_ENV *dbenv, const char *errpfx, const char *msg){ 703 | time_t curr_time = time(NULL); 704 | char time_str[32]; 705 | strftime(time_str, 32, "%c", localtime(&curr_time)); 706 | fprintf(stderr, "[%s] [%s] \"%s\"\n", errpfx, time_str, msg); 707 | } 708 | 709 | static void bdb_msg_callback(const DB_ENV *dbenv, const char *msg){ 710 | time_t curr_time = time(NULL); 711 | char time_str[32]; 712 | strftime(time_str, 32, "%c", localtime(&curr_time)); 713 | fprintf(stderr, "[%s] [%s] \"%s\"\n", PACKAGE, time_str, msg); 714 | } 715 | 716 | /* for atexit cleanup */ 717 | void bdb_chkpoint(void){ 718 | int ret = 0; 719 | if (envp != NULL){ 720 | ret = envp->txn_checkpoint(envp, 0, 0, 0); 721 | if (0 != ret){ 722 | fprintf(stderr, "envp->txn_checkpoint: %s\n", db_strerror(ret)); 723 | }else{ 724 | fprintf(stderr, "envp->txn_checkpoint: OK\n"); 725 | } 726 | } 727 | } 728 | 729 | 730 | -------------------------------------------------------------------------------- /compile: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Wrapper for compilers which do not understand `-c -o'. 3 | 4 | scriptversion=2005-05-14.22 5 | 6 | # Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc. 7 | # Written by Tom Tromey . 8 | # 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program; if not, write to the Free Software 21 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 22 | 23 | # As a special exception to the GNU General Public License, if you 24 | # distribute this file as part of a program that contains a 25 | # configuration script generated by Autoconf, you may include it under 26 | # the same distribution terms that you use for the rest of that program. 27 | 28 | # This file is maintained in Automake, please report 29 | # bugs to or send patches to 30 | # . 31 | 32 | case $1 in 33 | '') 34 | echo "$0: No command. Try \`$0 --help' for more information." 1>&2 35 | exit 1; 36 | ;; 37 | -h | --h*) 38 | cat <<\EOF 39 | Usage: compile [--help] [--version] PROGRAM [ARGS] 40 | 41 | Wrapper for compilers which do not understand `-c -o'. 42 | Remove `-o dest.o' from ARGS, run PROGRAM with the remaining 43 | arguments, and rename the output as expected. 44 | 45 | If you are trying to build a whole package this is not the 46 | right script to run: please start by reading the file `INSTALL'. 47 | 48 | Report bugs to . 49 | EOF 50 | exit $? 51 | ;; 52 | -v | --v*) 53 | echo "compile $scriptversion" 54 | exit $? 55 | ;; 56 | esac 57 | 58 | ofile= 59 | cfile= 60 | eat= 61 | 62 | for arg 63 | do 64 | if test -n "$eat"; then 65 | eat= 66 | else 67 | case $1 in 68 | -o) 69 | # configure might choose to run compile as `compile cc -o foo foo.c'. 70 | # So we strip `-o arg' only if arg is an object. 71 | eat=1 72 | case $2 in 73 | *.o | *.obj) 74 | ofile=$2 75 | ;; 76 | *) 77 | set x "$@" -o "$2" 78 | shift 79 | ;; 80 | esac 81 | ;; 82 | *.c) 83 | cfile=$1 84 | set x "$@" "$1" 85 | shift 86 | ;; 87 | *) 88 | set x "$@" "$1" 89 | shift 90 | ;; 91 | esac 92 | fi 93 | shift 94 | done 95 | 96 | if test -z "$ofile" || test -z "$cfile"; then 97 | # If no `-o' option was seen then we might have been invoked from a 98 | # pattern rule where we don't need one. That is ok -- this is a 99 | # normal compilation that the losing compiler can handle. If no 100 | # `.c' file was seen then we are probably linking. That is also 101 | # ok. 102 | exec "$@" 103 | fi 104 | 105 | # Name of file we expect compiler to create. 106 | cofile=`echo "$cfile" | sed -e 's|^.*/||' -e 's/\.c$/.o/'` 107 | 108 | # Create the lock directory. 109 | # Note: use `[/.-]' here to ensure that we don't use the same name 110 | # that we are using for the .o file. Also, base the name on the expected 111 | # object file name, since that is what matters with a parallel build. 112 | lockdir=`echo "$cofile" | sed -e 's|[/.-]|_|g'`.d 113 | while true; do 114 | if mkdir "$lockdir" >/dev/null 2>&1; then 115 | break 116 | fi 117 | sleep 1 118 | done 119 | # FIXME: race condition here if user kills between mkdir and trap. 120 | trap "rmdir '$lockdir'; exit 1" 1 2 15 121 | 122 | # Run the compile. 123 | "$@" 124 | ret=$? 125 | 126 | if test -f "$cofile"; then 127 | mv "$cofile" "$ofile" 128 | elif test -f "${cofile}bj"; then 129 | mv "${cofile}bj" "$ofile" 130 | fi 131 | 132 | rmdir "$lockdir" 133 | exit $ret 134 | 135 | # Local Variables: 136 | # mode: shell-script 137 | # sh-indentation: 2 138 | # eval: (add-hook 'write-file-hooks 'time-stamp) 139 | # time-stamp-start: "scriptversion=" 140 | # time-stamp-format: "%:y-%02m-%02d.%02H" 141 | # time-stamp-end: "$" 142 | # End: 143 | -------------------------------------------------------------------------------- /config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated from configure.ac by autoheader. */ 2 | 3 | /* Define this if you have daemon() */ 4 | #undef HAVE_DAEMON 5 | 6 | /* Define to 1 if you have the header file. */ 7 | #undef HAVE_DB_H 8 | 9 | /* Define to 1 if you have the header file. */ 10 | #undef HAVE_INTTYPES_H 11 | 12 | /* do we have malloc.h? */ 13 | #undef HAVE_MALLOC_H 14 | 15 | /* Define to 1 if you have the header file. */ 16 | #undef HAVE_MEMORY_H 17 | 18 | /* Define to 1 if stdbool.h conforms to C99. */ 19 | #undef HAVE_STDBOOL_H 20 | 21 | /* Define to 1 if you have the header file. */ 22 | #undef HAVE_STDINT_H 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #undef HAVE_STDLIB_H 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #undef HAVE_STRINGS_H 29 | 30 | /* Define to 1 if you have the header file. */ 31 | #undef HAVE_STRING_H 32 | 33 | /* do we have stuct mallinfo? */ 34 | #undef HAVE_STRUCT_MALLINFO 35 | 36 | /* Define to 1 if you have the header file. */ 37 | #undef HAVE_SYS_STAT_H 38 | 39 | /* Define to 1 if you have the header file. */ 40 | #undef HAVE_SYS_TYPES_H 41 | 42 | /* Define to 1 if you have the header file. */ 43 | #undef HAVE_UNISTD_H 44 | 45 | /* Define to 1 if the system has the type `_Bool'. */ 46 | #undef HAVE__BOOL 47 | 48 | /* Define to 1 if your C compiler doesn't accept -c and -o together. */ 49 | #undef NO_MINUS_C_MINUS_O 50 | 51 | /* Name of package */ 52 | #undef PACKAGE 53 | 54 | /* Define to the address where bug reports for this package should be sent. */ 55 | #undef PACKAGE_BUGREPORT 56 | 57 | /* Define to the full name of this package. */ 58 | #undef PACKAGE_NAME 59 | 60 | /* Define to the full name and version of this package. */ 61 | #undef PACKAGE_STRING 62 | 63 | /* Define to the one symbol short name of this package. */ 64 | #undef PACKAGE_TARNAME 65 | 66 | /* Define to the version of this package. */ 67 | #undef PACKAGE_VERSION 68 | 69 | /* Define to 1 if you have the ANSI C header files. */ 70 | #undef STDC_HEADERS 71 | 72 | /* Define this if you want to use pthreads */ 73 | #undef USE_THREADS 74 | 75 | /* Version number of package */ 76 | #undef VERSION 77 | 78 | /* Define to empty if `const' does not conform to ANSI C. */ 79 | #undef const 80 | 81 | /* define to int if socklen_t not available */ 82 | #undef socklen_t 83 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ(2.61) 2 | AC_INIT([memcacheq], [0.2.1], [stvchu@gmail.com]) 3 | AM_INIT_AUTOMAKE([-Wall -Werror foreign]) 4 | AC_PROG_CC 5 | AM_PROG_CC_C_O 6 | AC_CONFIG_HEADERS([config.h]) 7 | 8 | trylibeventdir="" 9 | AC_ARG_WITH(libevent, 10 | [ --with-libevent=PATH Specify path to libevent installation ], 11 | [ 12 | if test "x$withval" != "xno" ; then 13 | trylibeventdir=$withval 14 | fi 15 | ] 16 | ) 17 | 18 | dnl ------------------------------------------------------ 19 | dnl libevent detection. swiped from Tor. modified a bit. 20 | 21 | LIBEVENT_URL=http://www.monkey.org/~provos/libevent/ 22 | 23 | AC_CACHE_CHECK([for libevent directory], ac_cv_libevent_dir, [ 24 | saved_LIBS="$LIBS" 25 | saved_LDFLAGS="$LDFLAGS" 26 | saved_CPPFLAGS="$CPPFLAGS" 27 | le_found=no 28 | for ledir in $trylibeventdir "" $prefix /usr/local ; do 29 | LDFLAGS="$saved_LDFLAGS" 30 | LIBS="$saved_LIBS -levent" 31 | 32 | # Skip the directory if it isn't there. 33 | if test ! -z "$ledir" -a ! -d "$ledir" ; then 34 | continue; 35 | fi 36 | if test ! -z "$ledir" ; then 37 | if test -d "$ledir/lib" ; then 38 | LDFLAGS="-L$ledir/lib $LDFLAGS" 39 | else 40 | LDFLAGS="-L$ledir $LDFLAGS" 41 | fi 42 | if test -d "$ledir/include" ; then 43 | CPPFLAGS="-I$ledir/include $CPPFLAGS" 44 | else 45 | CPPFLAGS="-I$ledir $CPPFLAGS" 46 | fi 47 | fi 48 | # Can I compile and link it? 49 | AC_TRY_LINK([#include 50 | #include 51 | #include ], [ event_init(); ], 52 | [ libevent_linked=yes ], [ libevent_linked=no ]) 53 | if test $libevent_linked = yes; then 54 | if test ! -z "$ledir" ; then 55 | ac_cv_libevent_dir=$ledir 56 | else 57 | ac_cv_libevent_dir="(system)" 58 | fi 59 | le_found=yes 60 | break 61 | fi 62 | done 63 | LIBS="$saved_LIBS" 64 | LDFLAGS="$saved_LDFLAGS" 65 | CPPFLAGS="$saved_CPPFLAGS" 66 | if test $le_found = no ; then 67 | AC_MSG_ERROR([libevent is required. You can get it from $LIBEVENT_URL 68 | 69 | If it's already installed, specify its path using --with-libevent=/dir/ 70 | ]) 71 | fi 72 | ]) 73 | LIBS="$LIBS -levent" 74 | if test $ac_cv_libevent_dir != "(system)"; then 75 | if test -d "$ac_cv_libevent_dir/lib" ; then 76 | LDFLAGS="-L$ac_cv_libevent_dir/lib $LDFLAGS" 77 | le_libdir="$ac_cv_libevent_dir/lib" 78 | else 79 | LDFLAGS="-L$ac_cv_libevent_dir $LDFLAGS" 80 | le_libdir="$ac_cv_libevent_dir" 81 | fi 82 | if test -d "$ac_cv_libevent_dir/include" ; then 83 | CPPFLAGS="-I$ac_cv_libevent_dir/include $CPPFLAGS" 84 | else 85 | CPPFLAGS="-I$ac_cv_libevent_dir $CPPFLAGS" 86 | fi 87 | fi 88 | 89 | dnl Check BerkeleyDB lib and headers 90 | bdbdir="/usr/local/BerkeleyDB.4.7" 91 | AC_ARG_WITH(bdb, 92 | [ --with-bdb=PATH Specify path to BerkeleyDB installation ], 93 | [ 94 | if test "x$withval" != "xno" ; then 95 | bdbdir=$withval 96 | fi 97 | ] 98 | ) 99 | CPPFLAGS="-I$bdbdir/include $CPPFLAGS" 100 | LDFLAGS="-L$bdbdir/lib $LDFLAGS" 101 | AC_SEARCH_LIBS([db_create], [db], [] ,[AC_MSG_ERROR(cannot find libdb.so in $bdbdir/lib)]) 102 | AC_CHECK_HEADERS([db.h], [] ,[AC_MSG_ERROR(cannot find db.h in $bdbdir/include)]) 103 | 104 | dnl ---------------------------------------------------------------------------- 105 | 106 | AC_SEARCH_LIBS(socket, socket) 107 | AC_SEARCH_LIBS(gethostbyname, nsl) 108 | AC_SEARCH_LIBS(mallinfo, malloc) 109 | AC_SEARCH_LIBS(ceilf, m) 110 | 111 | AC_CHECK_FUNC(daemon,AC_DEFINE([HAVE_DAEMON],,[Define this if you have daemon()]),[AC_LIBOBJ(daemon)]) 112 | 113 | AC_HEADER_STDBOOL 114 | AC_C_CONST 115 | AC_CHECK_HEADER(malloc.h, AC_DEFINE(HAVE_MALLOC_H,,[do we have malloc.h?])) 116 | AC_CHECK_MEMBER([struct mallinfo.arena], [ 117 | AC_DEFINE(HAVE_STRUCT_MALLINFO,,[do we have stuct mallinfo?]) 118 | ], ,[ 119 | # include 120 | ] 121 | ) 122 | 123 | dnl From licq: Copyright (c) 2000 Dirk Mueller 124 | dnl Check if the type socklen_t is defined anywhere 125 | AC_DEFUN([AC_C_SOCKLEN_T], 126 | [AC_CACHE_CHECK(for socklen_t, ac_cv_c_socklen_t, 127 | [ 128 | AC_TRY_COMPILE([ 129 | #include 130 | #include 131 | ],[ 132 | socklen_t foo; 133 | ],[ 134 | ac_cv_c_socklen_t=yes 135 | ],[ 136 | ac_cv_c_socklen_t=no 137 | ]) 138 | ]) 139 | if test $ac_cv_c_socklen_t = no; then 140 | AC_DEFINE(socklen_t, int, [define to int if socklen_t not available]) 141 | fi 142 | ]) 143 | 144 | AC_C_SOCKLEN_T 145 | 146 | dnl Check whether the user wants threads or not 147 | AC_ARG_ENABLE(threads, 148 | [AS_HELP_STRING([--enable-threads],[support multithreaded execution])]) 149 | if test "x$enable_threads" == "xyes"; then 150 | AC_SEARCH_LIBS([pthread_create], [pthread], [AC_DEFINE([USE_THREADS],,[Define this if you want to use pthreads])] ,[AC_MSG_ERROR(cannot find libpthread.so)]) 151 | fi 152 | 153 | AC_CONFIG_FILES([Makefile tools/Makefile]) 154 | AC_OUTPUT 155 | -------------------------------------------------------------------------------- /daemon.c: -------------------------------------------------------------------------------- 1 | /* $Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $ */ 2 | /* $NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $ */ 3 | /*- 4 | * Copyright (c) 1990, 1993 5 | * The Regents of the University of California. All rights reserved. 6 | * 7 | * Redistribution and use in source and binary forms, with or without 8 | * modification, are permitted provided that the following conditions 9 | * are met: 10 | * 1. Redistributions of source code must retain the above copyright 11 | * notice, this list of conditions and the following disclaimer. 12 | * 2. Redistributions in binary form must reproduce the above copyright 13 | * notice, this list of conditions and the following disclaimer in the 14 | * documentation and/or other materials provided with the distribution. 15 | * 3. Neither the name of the University nor the names of its contributors 16 | * may be used to endorse or promote products derived from this software 17 | * without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 | * SUCH DAMAGE. 30 | */ 31 | 32 | #if defined __SUNPRO_C || defined __DECC || defined __HP_cc 33 | # pragma ident "@(#)$Header: /cvsroot/wikipedia/willow/src/bin/willow/daemon.c,v 1.1 2005/05/02 19:15:21 kateturner Exp $" 34 | # pragma ident "$NetBSD: daemon.c,v 1.9 2003/08/07 16:42:46 agc Exp $" 35 | #endif 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "memcacheq.h" 43 | 44 | int daemonize(int nochdir, int noclose) 45 | { 46 | int fd; 47 | 48 | switch (fork()) { 49 | case -1: 50 | return (-1); 51 | case 0: 52 | break; 53 | default: 54 | _exit(EXIT_SUCCESS); 55 | } 56 | 57 | if (setsid() == -1) 58 | return (-1); 59 | 60 | if (nochdir == 0) { 61 | if(chdir("/") != 0) { 62 | perror("chdir"); 63 | return (-1); 64 | } 65 | } 66 | 67 | if (noclose == 0 && (fd = open("/dev/null", O_RDWR, 0)) != -1) { 68 | if(dup2(fd, STDIN_FILENO) < 0) { 69 | perror("dup2 stdin"); 70 | return (-1); 71 | } 72 | if(dup2(fd, STDOUT_FILENO) < 0) { 73 | perror("dup2 stdout"); 74 | return (-1); 75 | } 76 | if(dup2(fd, STDERR_FILENO) < 0) { 77 | perror("dup2 stderr"); 78 | return (-1); 79 | } 80 | 81 | if (fd > STDERR_FILENO) { 82 | if(close(fd) < 0) { 83 | perror("close"); 84 | return (-1); 85 | } 86 | } 87 | } 88 | return (0); 89 | } 90 | -------------------------------------------------------------------------------- /depcomp: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # depcomp - compile a program generating dependencies as side-effects 3 | 4 | scriptversion=2006-10-15.18 5 | 6 | # Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006 Free Software 7 | # Foundation, Inc. 8 | 9 | # This program is free software; you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation; either version 2, or (at your option) 12 | # any later version. 13 | 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program; if not, write to the Free Software 21 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 22 | # 02110-1301, USA. 23 | 24 | # As a special exception to the GNU General Public License, if you 25 | # distribute this file as part of a program that contains a 26 | # configuration script generated by Autoconf, you may include it under 27 | # the same distribution terms that you use for the rest of that program. 28 | 29 | # Originally written by Alexandre Oliva . 30 | 31 | case $1 in 32 | '') 33 | echo "$0: No command. Try \`$0 --help' for more information." 1>&2 34 | exit 1; 35 | ;; 36 | -h | --h*) 37 | cat <<\EOF 38 | Usage: depcomp [--help] [--version] PROGRAM [ARGS] 39 | 40 | Run PROGRAMS ARGS to compile a file, generating dependencies 41 | as side-effects. 42 | 43 | Environment variables: 44 | depmode Dependency tracking mode. 45 | source Source file read by `PROGRAMS ARGS'. 46 | object Object file output by `PROGRAMS ARGS'. 47 | DEPDIR directory where to store dependencies. 48 | depfile Dependency file to output. 49 | tmpdepfile Temporary file to use when outputing dependencies. 50 | libtool Whether libtool is used (yes/no). 51 | 52 | Report bugs to . 53 | EOF 54 | exit $? 55 | ;; 56 | -v | --v*) 57 | echo "depcomp $scriptversion" 58 | exit $? 59 | ;; 60 | esac 61 | 62 | if test -z "$depmode" || test -z "$source" || test -z "$object"; then 63 | echo "depcomp: Variables source, object and depmode must be set" 1>&2 64 | exit 1 65 | fi 66 | 67 | # Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. 68 | depfile=${depfile-`echo "$object" | 69 | sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} 70 | tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} 71 | 72 | rm -f "$tmpdepfile" 73 | 74 | # Some modes work just like other modes, but use different flags. We 75 | # parameterize here, but still list the modes in the big case below, 76 | # to make depend.m4 easier to write. Note that we *cannot* use a case 77 | # here, because this file can only contain one case statement. 78 | if test "$depmode" = hp; then 79 | # HP compiler uses -M and no extra arg. 80 | gccflag=-M 81 | depmode=gcc 82 | fi 83 | 84 | if test "$depmode" = dashXmstdout; then 85 | # This is just like dashmstdout with a different argument. 86 | dashmflag=-xM 87 | depmode=dashmstdout 88 | fi 89 | 90 | case "$depmode" in 91 | gcc3) 92 | ## gcc 3 implements dependency tracking that does exactly what 93 | ## we want. Yay! Note: for some reason libtool 1.4 doesn't like 94 | ## it if -MD -MP comes after the -MF stuff. Hmm. 95 | ## Unfortunately, FreeBSD c89 acceptance of flags depends upon 96 | ## the command line argument order; so add the flags where they 97 | ## appear in depend2.am. Note that the slowdown incurred here 98 | ## affects only configure: in makefiles, %FASTDEP% shortcuts this. 99 | for arg 100 | do 101 | case $arg in 102 | -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; 103 | *) set fnord "$@" "$arg" ;; 104 | esac 105 | shift # fnord 106 | shift # $arg 107 | done 108 | "$@" 109 | stat=$? 110 | if test $stat -eq 0; then : 111 | else 112 | rm -f "$tmpdepfile" 113 | exit $stat 114 | fi 115 | mv "$tmpdepfile" "$depfile" 116 | ;; 117 | 118 | gcc) 119 | ## There are various ways to get dependency output from gcc. Here's 120 | ## why we pick this rather obscure method: 121 | ## - Don't want to use -MD because we'd like the dependencies to end 122 | ## up in a subdir. Having to rename by hand is ugly. 123 | ## (We might end up doing this anyway to support other compilers.) 124 | ## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like 125 | ## -MM, not -M (despite what the docs say). 126 | ## - Using -M directly means running the compiler twice (even worse 127 | ## than renaming). 128 | if test -z "$gccflag"; then 129 | gccflag=-MD, 130 | fi 131 | "$@" -Wp,"$gccflag$tmpdepfile" 132 | stat=$? 133 | if test $stat -eq 0; then : 134 | else 135 | rm -f "$tmpdepfile" 136 | exit $stat 137 | fi 138 | rm -f "$depfile" 139 | echo "$object : \\" > "$depfile" 140 | alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz 141 | ## The second -e expression handles DOS-style file names with drive letters. 142 | sed -e 's/^[^:]*: / /' \ 143 | -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" 144 | ## This next piece of magic avoids the `deleted header file' problem. 145 | ## The problem is that when a header file which appears in a .P file 146 | ## is deleted, the dependency causes make to die (because there is 147 | ## typically no way to rebuild the header). We avoid this by adding 148 | ## dummy dependencies for each header file. Too bad gcc doesn't do 149 | ## this for us directly. 150 | tr ' ' ' 151 | ' < "$tmpdepfile" | 152 | ## Some versions of gcc put a space before the `:'. On the theory 153 | ## that the space means something, we add a space to the output as 154 | ## well. 155 | ## Some versions of the HPUX 10.20 sed can't process this invocation 156 | ## correctly. Breaking it into two sed invocations is a workaround. 157 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 158 | rm -f "$tmpdepfile" 159 | ;; 160 | 161 | hp) 162 | # This case exists only to let depend.m4 do its work. It works by 163 | # looking at the text of this script. This case will never be run, 164 | # since it is checked for above. 165 | exit 1 166 | ;; 167 | 168 | sgi) 169 | if test "$libtool" = yes; then 170 | "$@" "-Wp,-MDupdate,$tmpdepfile" 171 | else 172 | "$@" -MDupdate "$tmpdepfile" 173 | fi 174 | stat=$? 175 | if test $stat -eq 0; then : 176 | else 177 | rm -f "$tmpdepfile" 178 | exit $stat 179 | fi 180 | rm -f "$depfile" 181 | 182 | if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files 183 | echo "$object : \\" > "$depfile" 184 | 185 | # Clip off the initial element (the dependent). Don't try to be 186 | # clever and replace this with sed code, as IRIX sed won't handle 187 | # lines with more than a fixed number of characters (4096 in 188 | # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; 189 | # the IRIX cc adds comments like `#:fec' to the end of the 190 | # dependency line. 191 | tr ' ' ' 192 | ' < "$tmpdepfile" \ 193 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ 194 | tr ' 195 | ' ' ' >> $depfile 196 | echo >> $depfile 197 | 198 | # The second pass generates a dummy entry for each header file. 199 | tr ' ' ' 200 | ' < "$tmpdepfile" \ 201 | | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ 202 | >> $depfile 203 | else 204 | # The sourcefile does not contain any dependencies, so just 205 | # store a dummy comment line, to avoid errors with the Makefile 206 | # "include basename.Plo" scheme. 207 | echo "#dummy" > "$depfile" 208 | fi 209 | rm -f "$tmpdepfile" 210 | ;; 211 | 212 | aix) 213 | # The C for AIX Compiler uses -M and outputs the dependencies 214 | # in a .u file. In older versions, this file always lives in the 215 | # current directory. Also, the AIX compiler puts `$object:' at the 216 | # start of each line; $object doesn't have directory information. 217 | # Version 6 uses the directory in both cases. 218 | stripped=`echo "$object" | sed 's/\(.*\)\..*$/\1/'` 219 | tmpdepfile="$stripped.u" 220 | if test "$libtool" = yes; then 221 | "$@" -Wc,-M 222 | else 223 | "$@" -M 224 | fi 225 | stat=$? 226 | 227 | if test -f "$tmpdepfile"; then : 228 | else 229 | stripped=`echo "$stripped" | sed 's,^.*/,,'` 230 | tmpdepfile="$stripped.u" 231 | fi 232 | 233 | if test $stat -eq 0; then : 234 | else 235 | rm -f "$tmpdepfile" 236 | exit $stat 237 | fi 238 | 239 | if test -f "$tmpdepfile"; then 240 | outname="$stripped.o" 241 | # Each line is of the form `foo.o: dependent.h'. 242 | # Do two passes, one to just change these to 243 | # `$object: dependent.h' and one to simply `dependent.h:'. 244 | sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" 245 | sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" 246 | else 247 | # The sourcefile does not contain any dependencies, so just 248 | # store a dummy comment line, to avoid errors with the Makefile 249 | # "include basename.Plo" scheme. 250 | echo "#dummy" > "$depfile" 251 | fi 252 | rm -f "$tmpdepfile" 253 | ;; 254 | 255 | icc) 256 | # Intel's C compiler understands `-MD -MF file'. However on 257 | # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c 258 | # ICC 7.0 will fill foo.d with something like 259 | # foo.o: sub/foo.c 260 | # foo.o: sub/foo.h 261 | # which is wrong. We want: 262 | # sub/foo.o: sub/foo.c 263 | # sub/foo.o: sub/foo.h 264 | # sub/foo.c: 265 | # sub/foo.h: 266 | # ICC 7.1 will output 267 | # foo.o: sub/foo.c sub/foo.h 268 | # and will wrap long lines using \ : 269 | # foo.o: sub/foo.c ... \ 270 | # sub/foo.h ... \ 271 | # ... 272 | 273 | "$@" -MD -MF "$tmpdepfile" 274 | stat=$? 275 | if test $stat -eq 0; then : 276 | else 277 | rm -f "$tmpdepfile" 278 | exit $stat 279 | fi 280 | rm -f "$depfile" 281 | # Each line is of the form `foo.o: dependent.h', 282 | # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. 283 | # Do two passes, one to just change these to 284 | # `$object: dependent.h' and one to simply `dependent.h:'. 285 | sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" 286 | # Some versions of the HPUX 10.20 sed can't process this invocation 287 | # correctly. Breaking it into two sed invocations is a workaround. 288 | sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | 289 | sed -e 's/$/ :/' >> "$depfile" 290 | rm -f "$tmpdepfile" 291 | ;; 292 | 293 | hp2) 294 | # The "hp" stanza above does not work with aCC (C++) and HP's ia64 295 | # compilers, which have integrated preprocessors. The correct option 296 | # to use with these is +Maked; it writes dependencies to a file named 297 | # 'foo.d', which lands next to the object file, wherever that 298 | # happens to be. 299 | # Much of this is similar to the tru64 case; see comments there. 300 | dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` 301 | test "x$dir" = "x$object" && dir= 302 | base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` 303 | if test "$libtool" = yes; then 304 | tmpdepfile1=$dir$base.d 305 | tmpdepfile2=$dir.libs/$base.d 306 | "$@" -Wc,+Maked 307 | else 308 | tmpdepfile1=$dir$base.d 309 | tmpdepfile2=$dir$base.d 310 | "$@" +Maked 311 | fi 312 | stat=$? 313 | if test $stat -eq 0; then : 314 | else 315 | rm -f "$tmpdepfile1" "$tmpdepfile2" 316 | exit $stat 317 | fi 318 | 319 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" 320 | do 321 | test -f "$tmpdepfile" && break 322 | done 323 | if test -f "$tmpdepfile"; then 324 | sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" 325 | # Add `dependent.h:' lines. 326 | sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" 327 | else 328 | echo "#dummy" > "$depfile" 329 | fi 330 | rm -f "$tmpdepfile" "$tmpdepfile2" 331 | ;; 332 | 333 | tru64) 334 | # The Tru64 compiler uses -MD to generate dependencies as a side 335 | # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. 336 | # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put 337 | # dependencies in `foo.d' instead, so we check for that too. 338 | # Subdirectories are respected. 339 | dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` 340 | test "x$dir" = "x$object" && dir= 341 | base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` 342 | 343 | if test "$libtool" = yes; then 344 | # With Tru64 cc, shared objects can also be used to make a 345 | # static library. This mechanism is used in libtool 1.4 series to 346 | # handle both shared and static libraries in a single compilation. 347 | # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. 348 | # 349 | # With libtool 1.5 this exception was removed, and libtool now 350 | # generates 2 separate objects for the 2 libraries. These two 351 | # compilations output dependencies in $dir.libs/$base.o.d and 352 | # in $dir$base.o.d. We have to check for both files, because 353 | # one of the two compilations can be disabled. We should prefer 354 | # $dir$base.o.d over $dir.libs/$base.o.d because the latter is 355 | # automatically cleaned when .libs/ is deleted, while ignoring 356 | # the former would cause a distcleancheck panic. 357 | tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 358 | tmpdepfile2=$dir$base.o.d # libtool 1.5 359 | tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 360 | tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 361 | "$@" -Wc,-MD 362 | else 363 | tmpdepfile1=$dir$base.o.d 364 | tmpdepfile2=$dir$base.d 365 | tmpdepfile3=$dir$base.d 366 | tmpdepfile4=$dir$base.d 367 | "$@" -MD 368 | fi 369 | 370 | stat=$? 371 | if test $stat -eq 0; then : 372 | else 373 | rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" 374 | exit $stat 375 | fi 376 | 377 | for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" 378 | do 379 | test -f "$tmpdepfile" && break 380 | done 381 | if test -f "$tmpdepfile"; then 382 | sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" 383 | # That's a tab and a space in the []. 384 | sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" 385 | else 386 | echo "#dummy" > "$depfile" 387 | fi 388 | rm -f "$tmpdepfile" 389 | ;; 390 | 391 | #nosideeffect) 392 | # This comment above is used by automake to tell side-effect 393 | # dependency tracking mechanisms from slower ones. 394 | 395 | dashmstdout) 396 | # Important note: in order to support this mode, a compiler *must* 397 | # always write the preprocessed file to stdout, regardless of -o. 398 | "$@" || exit $? 399 | 400 | # Remove the call to Libtool. 401 | if test "$libtool" = yes; then 402 | while test $1 != '--mode=compile'; do 403 | shift 404 | done 405 | shift 406 | fi 407 | 408 | # Remove `-o $object'. 409 | IFS=" " 410 | for arg 411 | do 412 | case $arg in 413 | -o) 414 | shift 415 | ;; 416 | $object) 417 | shift 418 | ;; 419 | *) 420 | set fnord "$@" "$arg" 421 | shift # fnord 422 | shift # $arg 423 | ;; 424 | esac 425 | done 426 | 427 | test -z "$dashmflag" && dashmflag=-M 428 | # Require at least two characters before searching for `:' 429 | # in the target name. This is to cope with DOS-style filenames: 430 | # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. 431 | "$@" $dashmflag | 432 | sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" 433 | rm -f "$depfile" 434 | cat < "$tmpdepfile" > "$depfile" 435 | tr ' ' ' 436 | ' < "$tmpdepfile" | \ 437 | ## Some versions of the HPUX 10.20 sed can't process this invocation 438 | ## correctly. Breaking it into two sed invocations is a workaround. 439 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 440 | rm -f "$tmpdepfile" 441 | ;; 442 | 443 | dashXmstdout) 444 | # This case only exists to satisfy depend.m4. It is never actually 445 | # run, as this mode is specially recognized in the preamble. 446 | exit 1 447 | ;; 448 | 449 | makedepend) 450 | "$@" || exit $? 451 | # Remove any Libtool call 452 | if test "$libtool" = yes; then 453 | while test $1 != '--mode=compile'; do 454 | shift 455 | done 456 | shift 457 | fi 458 | # X makedepend 459 | shift 460 | cleared=no 461 | for arg in "$@"; do 462 | case $cleared in 463 | no) 464 | set ""; shift 465 | cleared=yes ;; 466 | esac 467 | case "$arg" in 468 | -D*|-I*) 469 | set fnord "$@" "$arg"; shift ;; 470 | # Strip any option that makedepend may not understand. Remove 471 | # the object too, otherwise makedepend will parse it as a source file. 472 | -*|$object) 473 | ;; 474 | *) 475 | set fnord "$@" "$arg"; shift ;; 476 | esac 477 | done 478 | obj_suffix="`echo $object | sed 's/^.*\././'`" 479 | touch "$tmpdepfile" 480 | ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" 481 | rm -f "$depfile" 482 | cat < "$tmpdepfile" > "$depfile" 483 | sed '1,2d' "$tmpdepfile" | tr ' ' ' 484 | ' | \ 485 | ## Some versions of the HPUX 10.20 sed can't process this invocation 486 | ## correctly. Breaking it into two sed invocations is a workaround. 487 | sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" 488 | rm -f "$tmpdepfile" "$tmpdepfile".bak 489 | ;; 490 | 491 | cpp) 492 | # Important note: in order to support this mode, a compiler *must* 493 | # always write the preprocessed file to stdout. 494 | "$@" || exit $? 495 | 496 | # Remove the call to Libtool. 497 | if test "$libtool" = yes; then 498 | while test $1 != '--mode=compile'; do 499 | shift 500 | done 501 | shift 502 | fi 503 | 504 | # Remove `-o $object'. 505 | IFS=" " 506 | for arg 507 | do 508 | case $arg in 509 | -o) 510 | shift 511 | ;; 512 | $object) 513 | shift 514 | ;; 515 | *) 516 | set fnord "$@" "$arg" 517 | shift # fnord 518 | shift # $arg 519 | ;; 520 | esac 521 | done 522 | 523 | "$@" -E | 524 | sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ 525 | -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | 526 | sed '$ s: \\$::' > "$tmpdepfile" 527 | rm -f "$depfile" 528 | echo "$object : \\" > "$depfile" 529 | cat < "$tmpdepfile" >> "$depfile" 530 | sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" 531 | rm -f "$tmpdepfile" 532 | ;; 533 | 534 | msvisualcpp) 535 | # Important note: in order to support this mode, a compiler *must* 536 | # always write the preprocessed file to stdout, regardless of -o, 537 | # because we must use -o when running libtool. 538 | "$@" || exit $? 539 | IFS=" " 540 | for arg 541 | do 542 | case "$arg" in 543 | "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") 544 | set fnord "$@" 545 | shift 546 | shift 547 | ;; 548 | *) 549 | set fnord "$@" "$arg" 550 | shift 551 | shift 552 | ;; 553 | esac 554 | done 555 | "$@" -E | 556 | sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" 557 | rm -f "$depfile" 558 | echo "$object : \\" > "$depfile" 559 | . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" 560 | echo " " >> "$depfile" 561 | . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" 562 | rm -f "$tmpdepfile" 563 | ;; 564 | 565 | none) 566 | exec "$@" 567 | ;; 568 | 569 | *) 570 | echo "Unknown depmode $depmode" 1>&2 571 | exit 1 572 | ;; 573 | esac 574 | 575 | exit 0 576 | 577 | # Local Variables: 578 | # mode: shell-script 579 | # sh-indentation: 2 580 | # eval: (add-hook 'write-file-hooks 'time-stamp) 581 | # time-stamp-start: "scriptversion=" 582 | # time-stamp-format: "%:y-%02m-%02d.%02H" 583 | # time-stamp-end: "$" 584 | # End: 585 | -------------------------------------------------------------------------------- /docgen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | 4 | echo "rst2html.py ./README ./README.html" 5 | rst2html.py ./README ./README.html 6 | echo "rst2html.py ./INSTALL ./INSTALL.html" 7 | rst2html.py ./INSTALL ./INSTALL.html 8 | -------------------------------------------------------------------------------- /hash.c: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------------------- 2 | * MurmurHash2, by Austin Appleby 3 | * 4 | * Note - This code makes a few assumptions about how your machine behaves - 5 | * 6 | * 1. We can read a 4-byte value from any address without crashing 7 | * 2. sizeof(int) == 4 8 | * 9 | * And it has a few limitations - 10 | * 11 | * 1. It will not work incrementally. 12 | * 2. It will not produce the same results on little-endian and big-endian 13 | * machines. 14 | */ 15 | 16 | unsigned int murmurhash2 ( const void * key, int len, unsigned int seed ) 17 | { 18 | /* 'm' and 'r' are mixing constants generated offline. 19 | * They're not really 'magic', they just happen to work well. 20 | */ 21 | 22 | const unsigned int m = 0x5bd1e995; 23 | const int r = 24; 24 | 25 | /* Initialize the hash to a 'random' value */ 26 | 27 | unsigned int h = seed ^ len; 28 | 29 | /* Mix 4 bytes at a time into the hash */ 30 | 31 | const unsigned char * data = (const unsigned char *)key; 32 | 33 | while(len >= 4) 34 | { 35 | unsigned int k = *(unsigned int *)data; 36 | 37 | k *= m; 38 | k ^= k >> r; 39 | k *= m; 40 | 41 | h *= m; 42 | h ^= k; 43 | 44 | data += 4; 45 | len -= 4; 46 | } 47 | 48 | /* Handle the last few bytes of the input array */ 49 | 50 | switch(len) 51 | { 52 | case 3: h ^= data[2] << 16; 53 | case 2: h ^= data[1] << 8; 54 | case 1: h ^= data[0]; 55 | h *= m; 56 | }; 57 | 58 | /* Do a few final mixes of the hash to ensure the last few 59 | * bytes are well-incorporated. 60 | */ 61 | 62 | h ^= h >> 13; 63 | h *= m; 64 | h ^= h >> 15; 65 | 66 | return h; 67 | } 68 | -------------------------------------------------------------------------------- /hash.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | /* 3 | * MemcacheQ - Simple Queue Service over Memcache 4 | * 5 | * http://memcacheq.googlecode.com 6 | * 7 | * The source code of MemcacheQ is most based on MemcachDB: 8 | * 9 | * http://memcachedb.googlecode.com 10 | * 11 | * Copyright 2008 Steve Chu. All rights reserved. 12 | * 13 | * Use and distribution licensed under the BSD license. See 14 | * the LICENSE file for full text. 15 | * 16 | * Authors: 17 | * Steve Chu 18 | * 19 | */ 20 | 21 | #ifndef QLIST_H__ 22 | #define QLIST_H__ 23 | 24 | unsigned int murmurhash2( const void * key, int len, unsigned int seed ); 25 | 26 | #endif /* QLIST_H__ */ 27 | -------------------------------------------------------------------------------- /hashtable.c: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2004 Christopher Clark */ 2 | 3 | #include "hashtable.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | /* 10 | Credit for primes table: Aaron Krowne 11 | http://br.endernet.org/~akrowne/ 12 | http://planetmath.org/encyclopedia/GoodHashTablePrimes.html 13 | */ 14 | static const unsigned int primes[] = { 15 | 53, 97, 193, 389, 16 | 769, 1543, 3079, 6151, 17 | 12289, 24593, 49157, 98317, 18 | 196613, 393241, 786433, 1572869, 19 | 3145739, 6291469, 12582917, 25165843, 20 | 50331653, 100663319, 201326611, 402653189, 21 | 805306457, 1610612741 22 | }; 23 | const unsigned int prime_table_length = sizeof(primes)/sizeof(primes[0]); 24 | const float max_load_factor = 0.65; 25 | 26 | /*****************************************************************************/ 27 | struct hashtable * 28 | create_hashtable(unsigned int minsize, 29 | unsigned int (*hashf) (void*), 30 | int (*eqf) (void*,void*)) 31 | { 32 | struct hashtable *h; 33 | unsigned int pindex, size = primes[0]; 34 | /* Check requested hashtable isn't too large */ 35 | if (minsize > (1u << 30)) return NULL; 36 | /* Enforce size as prime */ 37 | for (pindex=0; pindex < prime_table_length; pindex++) { 38 | if (primes[pindex] > minsize) { size = primes[pindex]; break; } 39 | } 40 | h = (struct hashtable *)malloc(sizeof(struct hashtable)); 41 | if (NULL == h) return NULL; /*oom*/ 42 | h->table = (struct entry **)malloc(sizeof(struct entry*) * size); 43 | if (NULL == h->table) { free(h); return NULL; } /*oom*/ 44 | memset(h->table, 0, size * sizeof(struct entry *)); 45 | h->tablelength = size; 46 | h->primeindex = pindex; 47 | h->entrycount = 0; 48 | h->hashfn = hashf; 49 | h->eqfn = eqf; 50 | h->loadlimit = (unsigned int) ceil(size * max_load_factor); 51 | return h; 52 | } 53 | 54 | /*****************************************************************************/ 55 | unsigned int 56 | hash(struct hashtable *h, void *k) 57 | { 58 | /* Aim to protect against poor hash functions by adding logic here 59 | * - logic taken from java 1.4 hashtable source */ 60 | unsigned int i = h->hashfn(k); 61 | i += ~(i << 9); 62 | i ^= ((i >> 14) | (i << 18)); /* >>> */ 63 | i += (i << 4); 64 | i ^= ((i >> 10) | (i << 22)); /* >>> */ 65 | return i; 66 | } 67 | 68 | /*****************************************************************************/ 69 | static int 70 | hashtable_expand(struct hashtable *h) 71 | { 72 | /* Double the size of the table to accomodate more entries */ 73 | struct entry **newtable; 74 | struct entry *e; 75 | struct entry **pE; 76 | unsigned int newsize, i, index; 77 | /* Check we're not hitting max capacity */ 78 | if (h->primeindex == (prime_table_length - 1)) return 0; 79 | newsize = primes[++(h->primeindex)]; 80 | 81 | newtable = (struct entry **)malloc(sizeof(struct entry*) * newsize); 82 | if (NULL != newtable) 83 | { 84 | memset(newtable, 0, newsize * sizeof(struct entry *)); 85 | /* This algorithm is not 'stable'. ie. it reverses the list 86 | * when it transfers entries between the tables */ 87 | for (i = 0; i < h->tablelength; i++) { 88 | while (NULL != (e = h->table[i])) { 89 | h->table[i] = e->next; 90 | index = indexFor(newsize,e->h); 91 | e->next = newtable[index]; 92 | newtable[index] = e; 93 | } 94 | } 95 | free(h->table); 96 | h->table = newtable; 97 | } 98 | /* Plan B: realloc instead */ 99 | else 100 | { 101 | newtable = (struct entry **) 102 | realloc(h->table, newsize * sizeof(struct entry *)); 103 | if (NULL == newtable) { (h->primeindex)--; return 0; } 104 | h->table = newtable; 105 | memset(newtable[h->tablelength], 0, newsize - h->tablelength); 106 | for (i = 0; i < h->tablelength; i++) { 107 | for (pE = &(newtable[i]), e = *pE; e != NULL; e = *pE) { 108 | index = indexFor(newsize,e->h); 109 | if (index == i) 110 | { 111 | pE = &(e->next); 112 | } 113 | else 114 | { 115 | *pE = e->next; 116 | e->next = newtable[index]; 117 | newtable[index] = e; 118 | } 119 | } 120 | } 121 | } 122 | h->tablelength = newsize; 123 | h->loadlimit = (unsigned int) ceil(newsize * max_load_factor); 124 | return -1; 125 | } 126 | 127 | /*****************************************************************************/ 128 | unsigned int 129 | hashtable_count(struct hashtable *h) 130 | { 131 | return h->entrycount; 132 | } 133 | 134 | /*****************************************************************************/ 135 | int 136 | hashtable_insert(struct hashtable *h, void *k, void *v) 137 | { 138 | /* This method allows duplicate keys - but they shouldn't be used */ 139 | unsigned int index; 140 | struct entry *e; 141 | if (++(h->entrycount) > h->loadlimit) 142 | { 143 | /* Ignore the return value. If expand fails, we should 144 | * still try cramming just this value into the existing table 145 | * -- we may not have memory for a larger table, but one more 146 | * element may be ok. Next time we insert, we'll try expanding again.*/ 147 | hashtable_expand(h); 148 | } 149 | e = (struct entry *)malloc(sizeof(struct entry)); 150 | if (NULL == e) { --(h->entrycount); return 0; } /*oom*/ 151 | e->h = hash(h,k); 152 | index = indexFor(h->tablelength,e->h); 153 | e->k = k; 154 | e->v = v; 155 | e->next = h->table[index]; 156 | h->table[index] = e; 157 | return -1; 158 | } 159 | 160 | /*****************************************************************************/ 161 | void * /* returns value associated with key */ 162 | hashtable_search(struct hashtable *h, void *k) 163 | { 164 | struct entry *e; 165 | unsigned int hashvalue, index; 166 | hashvalue = hash(h,k); 167 | index = indexFor(h->tablelength,hashvalue); 168 | e = h->table[index]; 169 | while (NULL != e) 170 | { 171 | /* Check hash value to short circuit heavier comparison */ 172 | if ((hashvalue == e->h) && (h->eqfn(k, e->k))) return e->v; 173 | e = e->next; 174 | } 175 | return NULL; 176 | } 177 | 178 | /*****************************************************************************/ 179 | void * /* returns value associated with key */ 180 | hashtable_remove(struct hashtable *h, void *k) 181 | { 182 | /* TODO: consider compacting the table when the load factor drops enough, 183 | * or provide a 'compact' method. */ 184 | 185 | struct entry *e; 186 | struct entry **pE; 187 | void *v; 188 | unsigned int hashvalue, index; 189 | 190 | hashvalue = hash(h,k); 191 | index = indexFor(h->tablelength,hash(h,k)); 192 | pE = &(h->table[index]); 193 | e = *pE; 194 | while (NULL != e) 195 | { 196 | /* Check hash value to short circuit heavier comparison */ 197 | if ((hashvalue == e->h) && (h->eqfn(k, e->k))) 198 | { 199 | *pE = e->next; 200 | h->entrycount--; 201 | v = e->v; 202 | freekey(e->k); 203 | free(e); 204 | return v; 205 | } 206 | pE = &(e->next); 207 | e = e->next; 208 | } 209 | return NULL; 210 | } 211 | 212 | /*****************************************************************************/ 213 | /* destroy */ 214 | void 215 | hashtable_destroy(struct hashtable *h, int free_values) 216 | { 217 | unsigned int i; 218 | struct entry *e, *f; 219 | struct entry **table = h->table; 220 | if (free_values) 221 | { 222 | for (i = 0; i < h->tablelength; i++) 223 | { 224 | e = table[i]; 225 | while (NULL != e) 226 | { f = e; e = e->next; freekey(f->k); free(f->v); free(f); } 227 | } 228 | } 229 | else 230 | { 231 | for (i = 0; i < h->tablelength; i++) 232 | { 233 | e = table[i]; 234 | while (NULL != e) 235 | { f = e; e = e->next; freekey(f->k); free(f); } 236 | } 237 | } 238 | free(h->table); 239 | free(h); 240 | } 241 | 242 | /*****************************************************************************/ 243 | /* hashtable_iterator - iterator constructor */ 244 | 245 | struct hashtable_itr * 246 | hashtable_iterator(struct hashtable *h) 247 | { 248 | unsigned int i, tablelength; 249 | struct hashtable_itr *itr = (struct hashtable_itr *) 250 | malloc(sizeof(struct hashtable_itr)); 251 | if (NULL == itr) return NULL; 252 | itr->h = h; 253 | itr->e = NULL; 254 | itr->parent = NULL; 255 | tablelength = h->tablelength; 256 | itr->index = tablelength; 257 | if (0 == h->entrycount) return itr; 258 | 259 | for (i = 0; i < tablelength; i++) 260 | { 261 | if (NULL != h->table[i]) 262 | { 263 | itr->e = h->table[i]; 264 | itr->index = i; 265 | break; 266 | } 267 | } 268 | return itr; 269 | } 270 | 271 | /*****************************************************************************/ 272 | /* key - return the key of the (key,value) pair at the current position */ 273 | /* value - return the value of the (key,value) pair at the current position */ 274 | 275 | void * 276 | hashtable_iterator_key(struct hashtable_itr *i) 277 | { return i->e->k; } 278 | 279 | void * 280 | hashtable_iterator_value(struct hashtable_itr *i) 281 | { return i->e->v; } 282 | 283 | /*****************************************************************************/ 284 | /* advance - advance the iterator to the next element 285 | * returns zero if advanced to end of table */ 286 | 287 | int 288 | hashtable_iterator_advance(struct hashtable_itr *itr) 289 | { 290 | unsigned int j,tablelength; 291 | struct entry **table; 292 | struct entry *next; 293 | if (NULL == itr->e) return 0; /* stupidity check */ 294 | 295 | next = itr->e->next; 296 | if (NULL != next) 297 | { 298 | itr->parent = itr->e; 299 | itr->e = next; 300 | return -1; 301 | } 302 | tablelength = itr->h->tablelength; 303 | itr->parent = NULL; 304 | if (tablelength <= (j = ++(itr->index))) 305 | { 306 | itr->e = NULL; 307 | return 0; 308 | } 309 | table = itr->h->table; 310 | while (NULL == (next = table[j])) 311 | { 312 | if (++j >= tablelength) 313 | { 314 | itr->index = tablelength; 315 | itr->e = NULL; 316 | return 0; 317 | } 318 | } 319 | itr->index = j; 320 | itr->e = next; 321 | return -1; 322 | } 323 | 324 | /*****************************************************************************/ 325 | /* remove - remove the entry at the current iterator position 326 | * and advance the iterator, if there is a successive 327 | * element. 328 | * If you want the value, read it before you remove: 329 | * beware memory leaks if you don't. 330 | * Returns zero if end of iteration. */ 331 | 332 | int 333 | hashtable_iterator_remove(struct hashtable_itr *itr) 334 | { 335 | struct entry *remember_e, *remember_parent; 336 | int ret; 337 | 338 | /* Do the removal */ 339 | if (NULL == (itr->parent)) 340 | { 341 | /* element is head of a chain */ 342 | itr->h->table[itr->index] = itr->e->next; 343 | } else { 344 | /* element is mid-chain */ 345 | itr->parent->next = itr->e->next; 346 | } 347 | /* itr->e is now outside the hashtable */ 348 | remember_e = itr->e; 349 | itr->h->entrycount--; 350 | freekey(remember_e->k); 351 | 352 | /* Advance the iterator, correcting the parent */ 353 | remember_parent = itr->parent; 354 | ret = hashtable_iterator_advance(itr); 355 | if (itr->parent == remember_e) { itr->parent = remember_parent; } 356 | free(remember_e); 357 | return ret; 358 | } 359 | 360 | /*****************************************************************************/ 361 | int /* returns zero if not found */ 362 | hashtable_iterator_search(struct hashtable_itr *itr, 363 | struct hashtable *h, void *k) 364 | { 365 | struct entry *e, *parent; 366 | unsigned int hashvalue, index; 367 | 368 | hashvalue = hash(h,k); 369 | index = indexFor(h->tablelength,hashvalue); 370 | 371 | e = h->table[index]; 372 | parent = NULL; 373 | while (NULL != e) 374 | { 375 | /* Check hash value to short circuit heavier comparison */ 376 | if ((hashvalue == e->h) && (h->eqfn(k, e->k))) 377 | { 378 | itr->index = index; 379 | itr->e = e; 380 | itr->parent = parent; 381 | itr->h = h; 382 | return -1; 383 | } 384 | parent = e; 385 | e = e->next; 386 | } 387 | return 0; 388 | } 389 | 390 | 391 | /* 392 | * Copyright (c) 2002, Christopher Clark 393 | * All rights reserved. 394 | * 395 | * Redistribution and use in source and binary forms, with or without 396 | * modification, are permitted provided that the following conditions 397 | * are met: 398 | * 399 | * * Redistributions of source code must retain the above copyright 400 | * notice, this list of conditions and the following disclaimer. 401 | * 402 | * * Redistributions in binary form must reproduce the above copyright 403 | * notice, this list of conditions and the following disclaimer in the 404 | * documentation and/or other materials provided with the distribution. 405 | * 406 | * * Neither the name of the original author; nor the names of any contributors 407 | * may be used to endorse or promote products derived from this software 408 | * without specific prior written permission. 409 | * 410 | * 411 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 412 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 413 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 414 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 415 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 416 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 417 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 418 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 419 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 420 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 421 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 422 | */ 423 | -------------------------------------------------------------------------------- /hashtable.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2002 Christopher Clark */ 2 | 3 | #ifndef __HASHTABLE_CWC22_H__ 4 | #define __HASHTABLE_CWC22_H__ 5 | 6 | /*****************************************************************************/ 7 | struct entry 8 | { 9 | void *k, *v; 10 | unsigned int h; 11 | struct entry *next; 12 | }; 13 | 14 | struct hashtable { 15 | unsigned int tablelength; 16 | struct entry **table; 17 | unsigned int entrycount; 18 | unsigned int loadlimit; 19 | unsigned int primeindex; 20 | unsigned int (*hashfn) (void *k); 21 | int (*eqfn) (void *k1, void *k2); 22 | }; 23 | 24 | /*****************************************************************************/ 25 | unsigned int 26 | hash(struct hashtable *h, void *k); 27 | 28 | /*****************************************************************************/ 29 | /* indexFor */ 30 | static inline unsigned int 31 | indexFor(unsigned int tablelength, unsigned int hashvalue) { 32 | return (hashvalue % tablelength); 33 | }; 34 | 35 | /*****************************************************************************/ 36 | #define freekey(X) free(X) 37 | 38 | /*****************************************************************************/ 39 | 40 | /* Example of use: 41 | * 42 | * struct hashtable *h; 43 | * struct some_key *k; 44 | * struct some_value *v; 45 | * 46 | * static unsigned int hash_from_key_fn( void *k ); 47 | * static int keys_equal_fn ( void *key1, void *key2 ); 48 | * 49 | * h = create_hashtable(16, hash_from_key_fn, keys_equal_fn); 50 | * k = (struct some_key *) malloc(sizeof(struct some_key)); 51 | * v = (struct some_value *) malloc(sizeof(struct some_value)); 52 | * 53 | * (initialise k and v to suitable values) 54 | * 55 | * if (! hashtable_insert(h,k,v) ) 56 | * { exit(-1); } 57 | * 58 | * if (NULL == (found = hashtable_search(h,k) )) 59 | * { printf("not found!"); } 60 | * 61 | * if (NULL == (found = hashtable_remove(h,k) )) 62 | * { printf("Not found\n"); } 63 | * 64 | */ 65 | 66 | /* Macros may be used to define type-safe(r) hashtable access functions, with 67 | * methods specialized to take known key and value types as parameters. 68 | * 69 | * Example: 70 | * 71 | * Insert this at the start of your file: 72 | * 73 | * DEFINE_HASHTABLE_INSERT(insert_some, struct some_key, struct some_value); 74 | * DEFINE_HASHTABLE_SEARCH(search_some, struct some_key, struct some_value); 75 | * DEFINE_HASHTABLE_REMOVE(remove_some, struct some_key, struct some_value); 76 | * 77 | * This defines the functions 'insert_some', 'search_some' and 'remove_some'. 78 | * These operate just like hashtable_insert etc., with the same parameters, 79 | * but their function signatures have 'struct some_key *' rather than 80 | * 'void *', and hence can generate compile time errors if your program is 81 | * supplying incorrect data as a key (and similarly for value). 82 | * 83 | * Note that the hash and key equality functions passed to create_hashtable 84 | * still take 'void *' parameters instead of 'some key *'. This shouldn't be 85 | * a difficult issue as they're only defined and passed once, and the other 86 | * functions will ensure that only valid keys are supplied to them. 87 | * 88 | * The cost for this checking is increased code size and runtime overhead 89 | * - if performance is important, it may be worth switching back to the 90 | * unsafe methods once your program has been debugged with the safe methods. 91 | * This just requires switching to some simple alternative defines - eg: 92 | * #define insert_some hashtable_insert 93 | * 94 | */ 95 | 96 | /***************************************************************************** 97 | * create_hashtable 98 | 99 | * @name create_hashtable 100 | * @param minsize minimum initial size of hashtable 101 | * @param hashfunction function for hashing keys 102 | * @param key_eq_fn function for determining key equality 103 | * @return newly created hashtable or NULL on failure 104 | */ 105 | 106 | struct hashtable * 107 | create_hashtable(unsigned int minsize, 108 | unsigned int (*hashfunction) (void*), 109 | int (*key_eq_fn) (void*,void*)); 110 | 111 | /***************************************************************************** 112 | * hashtable_insert 113 | 114 | * @name hashtable_insert 115 | * @param h the hashtable to insert into 116 | * @param k the key - hashtable claims ownership and will free on removal 117 | * @param v the value - does not claim ownership 118 | * @return non-zero for successful insertion 119 | * 120 | * This function will cause the table to expand if the insertion would take 121 | * the ratio of entries to table size over the maximum load factor. 122 | * 123 | * This function does not check for repeated insertions with a duplicate key. 124 | * The value returned when using a duplicate key is undefined -- when 125 | * the hashtable changes size, the order of retrieval of duplicate key 126 | * entries is reversed. 127 | * If in doubt, remove before insert. 128 | */ 129 | 130 | int 131 | hashtable_insert(struct hashtable *h, void *k, void *v); 132 | 133 | /***************************************************************************** 134 | * hashtable_search 135 | 136 | * @name hashtable_search 137 | * @param h the hashtable to search 138 | * @param k the key to search for - does not claim ownership 139 | * @return the value associated with the key, or NULL if none found 140 | */ 141 | 142 | void * 143 | hashtable_search(struct hashtable *h, void *k); 144 | 145 | /***************************************************************************** 146 | * hashtable_remove 147 | 148 | * @name hashtable_remove 149 | * @param h the hashtable to remove the item from 150 | * @param k the key to search for - does not claim ownership 151 | * @return the value associated with the key, or NULL if none found 152 | */ 153 | 154 | void * /* returns value */ 155 | hashtable_remove(struct hashtable *h, void *k); 156 | 157 | /***************************************************************************** 158 | * hashtable_count 159 | 160 | * @name hashtable_count 161 | * @param h the hashtable 162 | * @return the number of items stored in the hashtable 163 | */ 164 | unsigned int 165 | hashtable_count(struct hashtable *h); 166 | 167 | /***************************************************************************** 168 | * hashtable_destroy 169 | 170 | * @name hashtable_destroy 171 | * @param h the hashtable 172 | * @param free_values whether to call 'free' on the remaining values 173 | */ 174 | 175 | void 176 | hashtable_destroy(struct hashtable *h, int free_values); 177 | 178 | /*****************************************************************************/ 179 | /* This struct is only concrete here to allow the inlining of two of the 180 | * accessor functions. */ 181 | struct hashtable_itr 182 | { 183 | struct hashtable *h; 184 | struct entry *e; 185 | struct entry *parent; 186 | unsigned int index; 187 | }; 188 | 189 | 190 | /*****************************************************************************/ 191 | /* hashtable_iterator 192 | */ 193 | 194 | struct hashtable_itr * 195 | hashtable_iterator(struct hashtable *h); 196 | 197 | /*****************************************************************************/ 198 | /* hashtable_iterator_key 199 | * - return the value of the (key,value) pair at the current position */ 200 | 201 | extern inline void * 202 | hashtable_iterator_key(struct hashtable_itr *i) 203 | { 204 | return i->e->k; 205 | } 206 | 207 | /*****************************************************************************/ 208 | /* value - return the value of the (key,value) pair at the current position */ 209 | 210 | extern inline void * 211 | hashtable_iterator_value(struct hashtable_itr *i) 212 | { 213 | return i->e->v; 214 | } 215 | 216 | /*****************************************************************************/ 217 | /* advance - advance the iterator to the next element 218 | * returns zero if advanced to end of table */ 219 | 220 | int 221 | hashtable_iterator_advance(struct hashtable_itr *itr); 222 | 223 | /*****************************************************************************/ 224 | /* remove - remove current element and advance the iterator to the next element 225 | * NB: if you need the value to free it, read it before 226 | * removing. ie: beware memory leaks! 227 | * returns zero if advanced to end of table */ 228 | 229 | int 230 | hashtable_iterator_remove(struct hashtable_itr *itr); 231 | 232 | /*****************************************************************************/ 233 | /* search - overwrite the supplied iterator, to point to the entry 234 | * matching the supplied key. 235 | h points to the hashtable to be searched. 236 | * returns zero if not found. */ 237 | int 238 | hashtable_iterator_search(struct hashtable_itr *itr, 239 | struct hashtable *h, void *k); 240 | 241 | #endif /* __HASHTABLE_CWC22_H__ */ 242 | 243 | /* 244 | * Copyright (c) 2002, Christopher Clark 245 | * All rights reserved. 246 | * 247 | * Redistribution and use in source and binary forms, with or without 248 | * modification, are permitted provided that the following conditions 249 | * are met: 250 | * 251 | * * Redistributions of source code must retain the above copyright 252 | * notice, this list of conditions and the following disclaimer. 253 | * 254 | * * Redistributions in binary form must reproduce the above copyright 255 | * notice, this list of conditions and the following disclaimer in the 256 | * documentation and/or other materials provided with the distribution. 257 | * 258 | * * Neither the name of the original author; nor the names of any contributors 259 | * may be used to endorse or promote products derived from this software 260 | * without specific prior written permission. 261 | * 262 | * 263 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 264 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 265 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 266 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 267 | * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 268 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 269 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 270 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 271 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 272 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 273 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274 | */ 275 | -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # install - install a program, script, or datafile 3 | 4 | scriptversion=2006-10-14.15 5 | 6 | # This originates from X11R5 (mit/util/scripts/install.sh), which was 7 | # later released in X11R6 (xc/config/util/install.sh) with the 8 | # following copyright and license. 9 | # 10 | # Copyright (C) 1994 X Consortium 11 | # 12 | # Permission is hereby granted, free of charge, to any person obtaining a copy 13 | # of this software and associated documentation files (the "Software"), to 14 | # deal in the Software without restriction, including without limitation the 15 | # rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 16 | # sell copies of the Software, and to permit persons to whom the Software is 17 | # furnished to do so, subject to the following conditions: 18 | # 19 | # The above copyright notice and this permission notice shall be included in 20 | # all copies or substantial portions of the Software. 21 | # 22 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | # X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 26 | # AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- 27 | # TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28 | # 29 | # Except as contained in this notice, the name of the X Consortium shall not 30 | # be used in advertising or otherwise to promote the sale, use or other deal- 31 | # ings in this Software without prior written authorization from the X Consor- 32 | # tium. 33 | # 34 | # 35 | # FSF changes to this file are in the public domain. 36 | # 37 | # Calling this script install-sh is preferred over install.sh, to prevent 38 | # `make' implicit rules from creating a file called install from it 39 | # when there is no Makefile. 40 | # 41 | # This script is compatible with the BSD install script, but was written 42 | # from scratch. 43 | 44 | nl=' 45 | ' 46 | IFS=" "" $nl" 47 | 48 | # set DOITPROG to echo to test this script 49 | 50 | # Don't use :- since 4.3BSD and earlier shells don't like it. 51 | doit="${DOITPROG-}" 52 | if test -z "$doit"; then 53 | doit_exec=exec 54 | else 55 | doit_exec=$doit 56 | fi 57 | 58 | # Put in absolute file names if you don't have them in your path; 59 | # or use environment vars. 60 | 61 | mvprog="${MVPROG-mv}" 62 | cpprog="${CPPROG-cp}" 63 | chmodprog="${CHMODPROG-chmod}" 64 | chownprog="${CHOWNPROG-chown}" 65 | chgrpprog="${CHGRPPROG-chgrp}" 66 | stripprog="${STRIPPROG-strip}" 67 | rmprog="${RMPROG-rm}" 68 | mkdirprog="${MKDIRPROG-mkdir}" 69 | 70 | posix_glob= 71 | posix_mkdir= 72 | 73 | # Desired mode of installed file. 74 | mode=0755 75 | 76 | chmodcmd=$chmodprog 77 | chowncmd= 78 | chgrpcmd= 79 | stripcmd= 80 | rmcmd="$rmprog -f" 81 | mvcmd="$mvprog" 82 | src= 83 | dst= 84 | dir_arg= 85 | dstarg= 86 | no_target_directory= 87 | 88 | usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE 89 | or: $0 [OPTION]... SRCFILES... DIRECTORY 90 | or: $0 [OPTION]... -t DIRECTORY SRCFILES... 91 | or: $0 [OPTION]... -d DIRECTORIES... 92 | 93 | In the 1st form, copy SRCFILE to DSTFILE. 94 | In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. 95 | In the 4th, create DIRECTORIES. 96 | 97 | Options: 98 | -c (ignored) 99 | -d create directories instead of installing files. 100 | -g GROUP $chgrpprog installed files to GROUP. 101 | -m MODE $chmodprog installed files to MODE. 102 | -o USER $chownprog installed files to USER. 103 | -s $stripprog installed files. 104 | -t DIRECTORY install into DIRECTORY. 105 | -T report an error if DSTFILE is a directory. 106 | --help display this help and exit. 107 | --version display version info and exit. 108 | 109 | Environment variables override the default commands: 110 | CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG 111 | " 112 | 113 | while test $# -ne 0; do 114 | case $1 in 115 | -c) shift 116 | continue;; 117 | 118 | -d) dir_arg=true 119 | shift 120 | continue;; 121 | 122 | -g) chgrpcmd="$chgrpprog $2" 123 | shift 124 | shift 125 | continue;; 126 | 127 | --help) echo "$usage"; exit $?;; 128 | 129 | -m) mode=$2 130 | shift 131 | shift 132 | case $mode in 133 | *' '* | *' '* | *' 134 | '* | *'*'* | *'?'* | *'['*) 135 | echo "$0: invalid mode: $mode" >&2 136 | exit 1;; 137 | esac 138 | continue;; 139 | 140 | -o) chowncmd="$chownprog $2" 141 | shift 142 | shift 143 | continue;; 144 | 145 | -s) stripcmd=$stripprog 146 | shift 147 | continue;; 148 | 149 | -t) dstarg=$2 150 | shift 151 | shift 152 | continue;; 153 | 154 | -T) no_target_directory=true 155 | shift 156 | continue;; 157 | 158 | --version) echo "$0 $scriptversion"; exit $?;; 159 | 160 | --) shift 161 | break;; 162 | 163 | -*) echo "$0: invalid option: $1" >&2 164 | exit 1;; 165 | 166 | *) break;; 167 | esac 168 | done 169 | 170 | if test $# -ne 0 && test -z "$dir_arg$dstarg"; then 171 | # When -d is used, all remaining arguments are directories to create. 172 | # When -t is used, the destination is already specified. 173 | # Otherwise, the last argument is the destination. Remove it from $@. 174 | for arg 175 | do 176 | if test -n "$dstarg"; then 177 | # $@ is not empty: it contains at least $arg. 178 | set fnord "$@" "$dstarg" 179 | shift # fnord 180 | fi 181 | shift # arg 182 | dstarg=$arg 183 | done 184 | fi 185 | 186 | if test $# -eq 0; then 187 | if test -z "$dir_arg"; then 188 | echo "$0: no input file specified." >&2 189 | exit 1 190 | fi 191 | # It's OK to call `install-sh -d' without argument. 192 | # This can happen when creating conditional directories. 193 | exit 0 194 | fi 195 | 196 | if test -z "$dir_arg"; then 197 | trap '(exit $?); exit' 1 2 13 15 198 | 199 | # Set umask so as not to create temps with too-generous modes. 200 | # However, 'strip' requires both read and write access to temps. 201 | case $mode in 202 | # Optimize common cases. 203 | *644) cp_umask=133;; 204 | *755) cp_umask=22;; 205 | 206 | *[0-7]) 207 | if test -z "$stripcmd"; then 208 | u_plus_rw= 209 | else 210 | u_plus_rw='% 200' 211 | fi 212 | cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; 213 | *) 214 | if test -z "$stripcmd"; then 215 | u_plus_rw= 216 | else 217 | u_plus_rw=,u+rw 218 | fi 219 | cp_umask=$mode$u_plus_rw;; 220 | esac 221 | fi 222 | 223 | for src 224 | do 225 | # Protect names starting with `-'. 226 | case $src in 227 | -*) src=./$src ;; 228 | esac 229 | 230 | if test -n "$dir_arg"; then 231 | dst=$src 232 | dstdir=$dst 233 | test -d "$dstdir" 234 | dstdir_status=$? 235 | else 236 | 237 | # Waiting for this to be detected by the "$cpprog $src $dsttmp" command 238 | # might cause directories to be created, which would be especially bad 239 | # if $src (and thus $dsttmp) contains '*'. 240 | if test ! -f "$src" && test ! -d "$src"; then 241 | echo "$0: $src does not exist." >&2 242 | exit 1 243 | fi 244 | 245 | if test -z "$dstarg"; then 246 | echo "$0: no destination specified." >&2 247 | exit 1 248 | fi 249 | 250 | dst=$dstarg 251 | # Protect names starting with `-'. 252 | case $dst in 253 | -*) dst=./$dst ;; 254 | esac 255 | 256 | # If destination is a directory, append the input filename; won't work 257 | # if double slashes aren't ignored. 258 | if test -d "$dst"; then 259 | if test -n "$no_target_directory"; then 260 | echo "$0: $dstarg: Is a directory" >&2 261 | exit 1 262 | fi 263 | dstdir=$dst 264 | dst=$dstdir/`basename "$src"` 265 | dstdir_status=0 266 | else 267 | # Prefer dirname, but fall back on a substitute if dirname fails. 268 | dstdir=` 269 | (dirname "$dst") 2>/dev/null || 270 | expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ 271 | X"$dst" : 'X\(//\)[^/]' \| \ 272 | X"$dst" : 'X\(//\)$' \| \ 273 | X"$dst" : 'X\(/\)' \| . 2>/dev/null || 274 | echo X"$dst" | 275 | sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ 276 | s//\1/ 277 | q 278 | } 279 | /^X\(\/\/\)[^/].*/{ 280 | s//\1/ 281 | q 282 | } 283 | /^X\(\/\/\)$/{ 284 | s//\1/ 285 | q 286 | } 287 | /^X\(\/\).*/{ 288 | s//\1/ 289 | q 290 | } 291 | s/.*/./; q' 292 | ` 293 | 294 | test -d "$dstdir" 295 | dstdir_status=$? 296 | fi 297 | fi 298 | 299 | obsolete_mkdir_used=false 300 | 301 | if test $dstdir_status != 0; then 302 | case $posix_mkdir in 303 | '') 304 | # Create intermediate dirs using mode 755 as modified by the umask. 305 | # This is like FreeBSD 'install' as of 1997-10-28. 306 | umask=`umask` 307 | case $stripcmd.$umask in 308 | # Optimize common cases. 309 | *[2367][2367]) mkdir_umask=$umask;; 310 | .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; 311 | 312 | *[0-7]) 313 | mkdir_umask=`expr $umask + 22 \ 314 | - $umask % 100 % 40 + $umask % 20 \ 315 | - $umask % 10 % 4 + $umask % 2 316 | `;; 317 | *) mkdir_umask=$umask,go-w;; 318 | esac 319 | 320 | # With -d, create the new directory with the user-specified mode. 321 | # Otherwise, rely on $mkdir_umask. 322 | if test -n "$dir_arg"; then 323 | mkdir_mode=-m$mode 324 | else 325 | mkdir_mode= 326 | fi 327 | 328 | posix_mkdir=false 329 | case $umask in 330 | *[123567][0-7][0-7]) 331 | # POSIX mkdir -p sets u+wx bits regardless of umask, which 332 | # is incompatible with FreeBSD 'install' when (umask & 300) != 0. 333 | ;; 334 | *) 335 | tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ 336 | trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 337 | 338 | if (umask $mkdir_umask && 339 | exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 340 | then 341 | if test -z "$dir_arg" || { 342 | # Check for POSIX incompatibilities with -m. 343 | # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or 344 | # other-writeable bit of parent directory when it shouldn't. 345 | # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. 346 | ls_ld_tmpdir=`ls -ld "$tmpdir"` 347 | case $ls_ld_tmpdir in 348 | d????-?r-*) different_mode=700;; 349 | d????-?--*) different_mode=755;; 350 | *) false;; 351 | esac && 352 | $mkdirprog -m$different_mode -p -- "$tmpdir" && { 353 | ls_ld_tmpdir_1=`ls -ld "$tmpdir"` 354 | test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" 355 | } 356 | } 357 | then posix_mkdir=: 358 | fi 359 | rmdir "$tmpdir/d" "$tmpdir" 360 | else 361 | # Remove any dirs left behind by ancient mkdir implementations. 362 | rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null 363 | fi 364 | trap '' 0;; 365 | esac;; 366 | esac 367 | 368 | if 369 | $posix_mkdir && ( 370 | umask $mkdir_umask && 371 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" 372 | ) 373 | then : 374 | else 375 | 376 | # The umask is ridiculous, or mkdir does not conform to POSIX, 377 | # or it failed possibly due to a race condition. Create the 378 | # directory the slow way, step by step, checking for races as we go. 379 | 380 | case $dstdir in 381 | /*) prefix=/ ;; 382 | -*) prefix=./ ;; 383 | *) prefix= ;; 384 | esac 385 | 386 | case $posix_glob in 387 | '') 388 | if (set -f) 2>/dev/null; then 389 | posix_glob=true 390 | else 391 | posix_glob=false 392 | fi ;; 393 | esac 394 | 395 | oIFS=$IFS 396 | IFS=/ 397 | $posix_glob && set -f 398 | set fnord $dstdir 399 | shift 400 | $posix_glob && set +f 401 | IFS=$oIFS 402 | 403 | prefixes= 404 | 405 | for d 406 | do 407 | test -z "$d" && continue 408 | 409 | prefix=$prefix$d 410 | if test -d "$prefix"; then 411 | prefixes= 412 | else 413 | if $posix_mkdir; then 414 | (umask=$mkdir_umask && 415 | $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break 416 | # Don't fail if two instances are running concurrently. 417 | test -d "$prefix" || exit 1 418 | else 419 | case $prefix in 420 | *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; 421 | *) qprefix=$prefix;; 422 | esac 423 | prefixes="$prefixes '$qprefix'" 424 | fi 425 | fi 426 | prefix=$prefix/ 427 | done 428 | 429 | if test -n "$prefixes"; then 430 | # Don't fail if two instances are running concurrently. 431 | (umask $mkdir_umask && 432 | eval "\$doit_exec \$mkdirprog $prefixes") || 433 | test -d "$dstdir" || exit 1 434 | obsolete_mkdir_used=true 435 | fi 436 | fi 437 | fi 438 | 439 | if test -n "$dir_arg"; then 440 | { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && 441 | { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && 442 | { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || 443 | test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 444 | else 445 | 446 | # Make a couple of temp file names in the proper directory. 447 | dsttmp=$dstdir/_inst.$$_ 448 | rmtmp=$dstdir/_rm.$$_ 449 | 450 | # Trap to clean up those temp files at exit. 451 | trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 452 | 453 | # Copy the file name to the temp name. 454 | (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && 455 | 456 | # and set any options; do chmod last to preserve setuid bits. 457 | # 458 | # If any of these fail, we abort the whole thing. If we want to 459 | # ignore errors from any of these, just make sure not to ignore 460 | # errors from the above "$doit $cpprog $src $dsttmp" command. 461 | # 462 | { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ 463 | && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ 464 | && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ 465 | && { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && 466 | 467 | # Now rename the file to the real destination. 468 | { $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null \ 469 | || { 470 | # The rename failed, perhaps because mv can't rename something else 471 | # to itself, or perhaps because mv is so ancient that it does not 472 | # support -f. 473 | 474 | # Now remove or move aside any old file at destination location. 475 | # We try this two ways since rm can't unlink itself on some 476 | # systems and the destination file might be busy for other 477 | # reasons. In this case, the final cleanup might fail but the new 478 | # file should still install successfully. 479 | { 480 | if test -f "$dst"; then 481 | $doit $rmcmd -f "$dst" 2>/dev/null \ 482 | || { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null \ 483 | && { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }; }\ 484 | || { 485 | echo "$0: cannot unlink or rename $dst" >&2 486 | (exit 1); exit 1 487 | } 488 | else 489 | : 490 | fi 491 | } && 492 | 493 | # Now rename the file to the real destination. 494 | $doit $mvcmd "$dsttmp" "$dst" 495 | } 496 | } || exit 1 497 | 498 | trap '' 0 499 | fi 500 | done 501 | 502 | # Local variables: 503 | # eval: (add-hook 'write-file-hooks 'time-stamp) 504 | # time-stamp-start: "scriptversion=" 505 | # time-stamp-format: "%:y-%02m-%02d.%02H" 506 | # time-stamp-end: "$" 507 | # End: 508 | -------------------------------------------------------------------------------- /item.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | /* 3 | * MemcacheQ - Simple Queue Service over Memcache 4 | * 5 | * http://memcacheq.googlecode.com 6 | * 7 | * The source code of MemcacheQ is most based on MemcachDB: 8 | * 9 | * http://memcachedb.googlecode.com 10 | * 11 | * Copyright 2008 Steve Chu. All rights reserved. 12 | * 13 | * Use and distribution licensed under the BSD license. See 14 | * the LICENSE file for full text. 15 | * 16 | * Authors: 17 | * Steve Chu 18 | * 19 | */ 20 | 21 | #include "memcacheq.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #define MAX_ITEM_FREELIST_LENGTH 4000 33 | #define INIT_ITEM_FREELIST_LENGTH 500 34 | 35 | static size_t item_make_header(const uint8_t nkey, const int flags, const int nbytes, char *suffix, uint8_t *nsuffix); 36 | 37 | static item **freeitem; 38 | static int freeitemtotal; 39 | static int freeitemcurr; 40 | 41 | void item_init(void) { 42 | freeitemtotal = INIT_ITEM_FREELIST_LENGTH; 43 | freeitemcurr = 0; 44 | 45 | freeitem = (item **)malloc( sizeof(item *) * freeitemtotal ); 46 | if (freeitem == NULL) { 47 | perror("malloc()"); 48 | } 49 | return; 50 | } 51 | 52 | /* 53 | * Returns a item buffer from the freelist, if any. Sholud call 54 | * item_from_freelist for thread safty. 55 | * */ 56 | item *do_item_from_freelist(void) { 57 | item *s; 58 | 59 | if (freeitemcurr > 0) { 60 | s = freeitem[--freeitemcurr]; 61 | } else { 62 | /* If malloc fails, let the logic fall through without spamming 63 | * STDERR on the server. */ 64 | s = (item *)malloc( bdb_settings.re_len ); 65 | if (s != NULL){ 66 | memset(s, 0, bdb_settings.re_len); 67 | } 68 | } 69 | 70 | return s; 71 | } 72 | 73 | /* 74 | * Adds a item to the freelist. Should call 75 | * item_add_to_freelist for thread safty. 76 | */ 77 | int do_item_add_to_freelist(item *it) { 78 | if (freeitemcurr < freeitemtotal) { 79 | freeitem[freeitemcurr++] = it; 80 | return 0; 81 | } else { 82 | if (freeitemtotal >= MAX_ITEM_FREELIST_LENGTH){ 83 | return 1; 84 | } 85 | /* try to enlarge free item buffer array */ 86 | item **new_freeitem = (item **)realloc(freeitem, sizeof(item *) * freeitemtotal * 2); 87 | if (new_freeitem) { 88 | freeitemtotal *= 2; 89 | freeitem = new_freeitem; 90 | freeitem[freeitemcurr++] = it; 91 | return 0; 92 | } 93 | } 94 | return 1; 95 | } 96 | 97 | /** 98 | * Generates the variable-sized part of the header for an object. 99 | * 100 | * key - The key 101 | * nkey - The length of the key 102 | * flags - key flags 103 | * nbytes - Number of bytes to hold value and addition CRLF terminator 104 | * suffix - Buffer for the "VALUE" line suffix (flags, size). 105 | * nsuffix - The length of the suffix is stored here. 106 | * 107 | * Returns the total size of the header. 108 | */ 109 | static size_t item_make_header(const uint8_t nkey, const int flags, const int nbytes, 110 | char *suffix, uint8_t *nsuffix) { 111 | /* suffix is defined at 40 chars elsewhere.. */ 112 | *nsuffix = (uint8_t) snprintf(suffix, 40, " %d %d\r\n", flags, nbytes - 2); 113 | return sizeof(item) + nkey + *nsuffix + nbytes; 114 | } 115 | 116 | /* 117 | * alloc a item buffer, and init it. 118 | */ 119 | item *item_alloc1(char *key, const size_t nkey, const int flags, const int nbytes) { 120 | uint8_t nsuffix; 121 | item *it; 122 | char suffix[40]; 123 | size_t ntotal = item_make_header(nkey + 1, flags, nbytes, suffix, &nsuffix); 124 | 125 | if(ntotal > bdb_settings.re_len){ 126 | return NULL; 127 | } 128 | 129 | it = item_from_freelist(); 130 | if (it == NULL){ 131 | return NULL; 132 | } 133 | if (settings.verbose > 1) { 134 | fprintf(stderr, "alloc a item buffer from freelist.\n"); 135 | } 136 | 137 | it->nkey = nkey; 138 | it->nbytes = nbytes; 139 | strcpy(ITEM_key(it), key); 140 | memcpy(ITEM_suffix(it), suffix, (size_t)nsuffix); 141 | it->nsuffix = nsuffix; 142 | return it; 143 | } 144 | 145 | /* 146 | * alloc a item buffer only. 147 | */ 148 | item *item_alloc2(void) { 149 | item *it; 150 | 151 | it = item_from_freelist(); 152 | if (it == NULL){ 153 | return NULL; 154 | } 155 | if (settings.verbose > 1) { 156 | fprintf(stderr, "alloc a item buffer from freelist.\n"); 157 | } 158 | 159 | return it; 160 | } 161 | 162 | /* 163 | * free a item buffer. 164 | */ 165 | 166 | int item_free(item *it) { 167 | if (NULL == it) 168 | return 0; 169 | 170 | if (0 != item_add_to_freelist(it)) { 171 | if (settings.verbose > 1) { 172 | fprintf(stderr, "add a item buffer to freelist fail, use free() directly.\n"); 173 | } 174 | free(it); 175 | }else{ 176 | if (settings.verbose > 1) { 177 | fprintf(stderr, "add a item buffer to freelist.\n"); 178 | } 179 | } 180 | return 0; 181 | } -------------------------------------------------------------------------------- /memcacheq.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | /* 3 | * MemcacheQ - Simple Queue Service over Memcache 4 | * 5 | * http://memcacheq.googlecode.com 6 | * 7 | * The source code of MemcacheQ is most based on MemcachDB: 8 | * 9 | * http://memcachedb.googlecode.com 10 | * 11 | * Copyright 2008 Steve Chu. All rights reserved. 12 | * 13 | * Use and distribution licensed under the BSD license. See 14 | * the LICENSE file for full text. 15 | * 16 | * Authors: 17 | * Steve Chu 18 | * 19 | */ 20 | 21 | #ifdef HAVE_CONFIG_H 22 | #include "config.h" 23 | #endif 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "hashtable.h" 33 | #include "hash.h" 34 | 35 | #define DATA_BUFFER_SIZE 2048 36 | #define UDP_READ_BUFFER_SIZE 65536 37 | #define UDP_MAX_PAYLOAD_SIZE 1400 38 | #define UDP_HEADER_SIZE 8 39 | #define MAX_SENDBUF_SIZE (256 * 1024 * 1024) 40 | /* I'm told the max legnth of a 64-bit num converted to string is 20 bytes. 41 | * Plus a few for spaces, \r\n, \0 */ 42 | #define SUFFIX_SIZE 24 43 | 44 | /** Initial size of list of items being returned by "get". */ 45 | #define ITEM_LIST_INITIAL 200 46 | 47 | /** Initial size of the sendmsg() scatter/gather array. */ 48 | #define IOV_LIST_INITIAL 400 49 | 50 | /** Initial number of sendmsg() argument structures to allocate. */ 51 | #define MSG_LIST_INITIAL 10 52 | 53 | /** High water marks for buffer shrinking */ 54 | #define READ_BUFFER_HIGHWAT 8192 55 | #define ITEM_LIST_HIGHWAT 400 56 | #define IOV_LIST_HIGHWAT 600 57 | #define MSG_LIST_HIGHWAT 100 58 | 59 | /* Get a consistent bool type */ 60 | #if HAVE_STDBOOL_H 61 | # include 62 | #else 63 | typedef enum {false = 0, true = 1} bool; 64 | #endif 65 | 66 | #if HAVE_STDINT_H 67 | # include 68 | #else 69 | typedef unsigned char uint8_t; 70 | #endif 71 | 72 | /* unistd.h is here */ 73 | #if HAVE_UNISTD_H 74 | # include 75 | #endif 76 | 77 | struct stats { 78 | unsigned int curr_conns; 79 | unsigned int total_conns; 80 | unsigned int conn_structs; 81 | uint64_t get_cmds; 82 | uint64_t get_hits; 83 | uint64_t set_cmds; 84 | uint64_t set_hits; 85 | time_t started; /* when the process was started */ 86 | uint64_t bytes_read; 87 | uint64_t bytes_written; 88 | }; 89 | 90 | #define MAX_VERBOSITY_LEVEL 2 91 | 92 | struct settings { 93 | int maxconns; 94 | int port; 95 | int udpport; 96 | char *inter; 97 | int verbose; 98 | char *socketpath; /* path to unix socket if using local socket */ 99 | int access; /* access mask (a la chmod) for unix domain socket */ 100 | int num_threads; /* number of libevent threads to run */ 101 | }; 102 | 103 | extern struct stats stats; 104 | extern struct settings settings; 105 | 106 | typedef struct _stritem { 107 | int nbytes; /* size of data */ 108 | uint8_t nsuffix; /* length of flags-and-length string */ 109 | uint8_t nkey; /* key length, w/terminating null and padding */ 110 | void * end[]; 111 | /* then null-terminated key */ 112 | /* then " flags length\r\n" (no terminating null) */ 113 | /* then data with terminating \r\n (no terminating null; it's binary!) */ 114 | } item; 115 | 116 | #define ITEM_key(item) ((char*)&((item)->end[0])) 117 | 118 | /* warning: don't use these macros with a function, as it evals its arg twice */ 119 | #define ITEM_suffix(item) ((char*) &((item)->end[0]) + (item)->nkey + 1) 120 | #define ITEM_data(item) ((char*) &((item)->end[0]) + (item)->nkey + 1 + (item)->nsuffix) 121 | #define ITEM_ntotal(item) (sizeof(struct _stritem) + (item)->nkey + 1 + (item)->nsuffix + (item)->nbytes) 122 | 123 | enum conn_states { 124 | conn_listening, /** the socket which listens for connections */ 125 | conn_read, /** reading in a command line */ 126 | conn_write, /** writing out a simple response */ 127 | conn_nread, /** reading in a fixed number of bytes */ 128 | conn_swallow, /** swallowing unnecessary bytes w/o storing */ 129 | conn_closing, /** closing this connection */ 130 | conn_mwrite, /** writing out many items sequentially */ 131 | }; 132 | 133 | typedef struct conn conn; 134 | struct conn { 135 | int sfd; 136 | int state; 137 | struct event event; 138 | short ev_flags; 139 | short which; /** which events were just triggered */ 140 | 141 | char *rbuf; /** buffer to read commands into */ 142 | char *rcurr; /** but if we parsed some already, this is where we stopped */ 143 | int rsize; /** total allocated size of rbuf */ 144 | int rbytes; /** how much data, starting from rcur, do we have unparsed */ 145 | 146 | char *wbuf; 147 | char *wcurr; 148 | int wsize; 149 | int wbytes; 150 | int write_and_go; /** which state to go into after finishing current write */ 151 | void *write_and_free; /** free this memory after finishing writing */ 152 | 153 | char *ritem; /** when we read in an item's value, it goes here */ 154 | int rlbytes; 155 | 156 | /* data for the nread state */ 157 | 158 | /** 159 | * item is used to hold an item structure created after reading the command 160 | * line of set/add/replace commands, but before we finished reading the actual 161 | * data. The data is read into ITEM_data(item) to avoid extra copying. 162 | */ 163 | 164 | void *item; /* for commands set/add/replace */ 165 | int item_comm; /* which one is it: set/add/replace */ 166 | 167 | /* data for the swallow state */ 168 | int sbytes; /* how many bytes to swallow */ 169 | 170 | /* data for the mwrite state */ 171 | struct iovec *iov; 172 | int iovsize; /* number of elements allocated in iov[] */ 173 | int iovused; /* number of elements used in iov[] */ 174 | 175 | struct msghdr *msglist; 176 | int msgsize; /* number of elements allocated in msglist[] */ 177 | int msgused; /* number of elements used in msglist[] */ 178 | int msgcurr; /* element in msglist[] being transmitted now */ 179 | int msgbytes; /* number of bytes in current msg */ 180 | 181 | item **ilist; /* list of items to write out */ 182 | int isize; 183 | item **icurr; 184 | int ileft; 185 | 186 | /* data for UDP clients */ 187 | bool udp; /* is this is a UDP "connection" */ 188 | int request_id; /* Incoming UDP request ID, if this is a UDP "connection" */ 189 | struct sockaddr request_addr; /* Who sent the most recent request */ 190 | socklen_t request_addr_size; 191 | unsigned char *hdrbuf; /* udp packet headers */ 192 | int hdrsize; /* number of headers' worth of space is allocated */ 193 | conn *next; /* Used for generating a list of conn structures */ 194 | }; 195 | 196 | /* 197 | * Functions 198 | */ 199 | 200 | /* item buffer management */ 201 | void item_init(void); 202 | item *do_item_from_freelist(void); 203 | int do_item_add_to_freelist(item *it); 204 | item *item_alloc1(char *key, const size_t nkey, const int flags, const int nbytes); 205 | item *item_alloc2(void); 206 | int item_free(item *it); 207 | 208 | /* conn management */ 209 | conn *do_conn_from_freelist(); 210 | bool do_conn_add_to_freelist(conn *c); 211 | conn *conn_new(const int sfd, const int init_state, const int event_flags, const int read_buffer_size, const bool is_udp, struct event_base *base); 212 | 213 | /* bdb */ 214 | #define DBHOME "/data1/memcacheq" 215 | 216 | #define BDB_CLEANUP_DBT() \ 217 | memset(&dbkey, 0, sizeof(dbkey)); \ 218 | memset(&dbdata, 0, sizeof(dbdata)) 219 | 220 | struct bdb_settings { 221 | char *env_home; 222 | u_int32_t cache_size; 223 | u_int32_t txn_lg_bsize; 224 | u_int32_t log_auto_remove; 225 | u_int32_t page_size; 226 | int txn_nosync; 227 | int deadlock_detect_val; 228 | int checkpoint_val; 229 | int mempool_trickle_val; 230 | int mempool_trickle_percent; 231 | int qstats_dump_val; 232 | u_int32_t re_len; 233 | u_int32_t q_extentsize; 234 | }; 235 | 236 | typedef struct _qstats { 237 | int64_t set_hits; 238 | int64_t get_hits; 239 | } qstats_t; 240 | 241 | typedef struct _queue { 242 | DB* dbp; 243 | int64_t set_hits; 244 | int64_t get_hits; 245 | int64_t old_set_hits; 246 | int64_t old_get_hits; 247 | pthread_mutex_t lock; 248 | } queue_t; 249 | 250 | extern struct bdb_settings bdb_settings; 251 | extern DB_ENV *envp; 252 | 253 | void qlist_ht_init(void); 254 | void qlist_ht_close(void); 255 | void bdb_settings_init(void); 256 | void bdb_env_init(void); 257 | void bdb_env_close(void); 258 | void bdb_qlist_db_open(void); 259 | void bdb_qlist_db_close(void); 260 | int bdb_create_queue(char *queue_name); 261 | int bdb_delete_queue(char *queue_name); 262 | int bdb_set(char *key, item *it); 263 | item* bdb_get(char *key); 264 | void print_queue_stats(char *temp, int len_limit); 265 | 266 | void start_checkpoint_thread(void); 267 | void start_mempool_trickle_thread(void); 268 | void start_deadlock_detect_thread(void); 269 | void start_qstats_dump_thread(void); 270 | void bdb_chkpoint(void); 271 | 272 | /* 273 | * In multithreaded mode, we wrap certain functions with lock management and 274 | * replace the logic of some other functions. All wrapped functions have 275 | * "mt_" and "do_" variants. In multithreaded mode, the plain version of a 276 | * function is #define-d to the "mt_" variant, which often just grabs a 277 | * lock and calls the "do_" function. In singlethreaded mode, the "do_" 278 | * function is called directly. 279 | * 280 | * Functions such as the libevent-related calls that need to do cross-thread 281 | * communication in multithreaded mode (rather than actually doing the work 282 | * in the current thread) are called via "dispatch_" frontends, which are 283 | * also #define-d to directly call the underlying code in singlethreaded mode. 284 | */ 285 | #ifdef USE_THREADS 286 | 287 | void thread_init(int nthreads, struct event_base *main_base); 288 | int dispatch_event_add(int thread, conn *c); 289 | void dispatch_conn_new(int sfd, int init_state, int event_flags, int read_buffer_size, int is_udp); 290 | 291 | /* Lock wrappers for cache functions that are called from main loop. */ 292 | conn *mt_conn_from_freelist(void); 293 | bool mt_conn_add_to_freelist(conn *c); 294 | int mt_is_listen_thread(void); 295 | item *mt_item_from_freelist(void); 296 | int mt_item_add_to_freelist(item *it); 297 | void mt_stats_lock(void); 298 | void mt_stats_unlock(void); 299 | 300 | # define conn_from_freelist() mt_conn_from_freelist() 301 | # define conn_add_to_freelist(x) mt_conn_add_to_freelist(x) 302 | # define is_listen_thread() mt_is_listen_thread() 303 | # define item_from_freelist() mt_item_from_freelist() 304 | # define item_add_to_freelist(x) mt_item_add_to_freelist(x) 305 | 306 | # define STATS_LOCK() mt_stats_lock() 307 | # define STATS_UNLOCK() mt_stats_unlock() 308 | 309 | #else /* !USE_THREADS */ 310 | 311 | # define conn_from_freelist() do_conn_from_freelist() 312 | # define conn_add_to_freelist(x) do_conn_add_to_freelist(x) 313 | # define dispatch_conn_new(x,y,z,a,b) conn_new(x,y,z,a,b,main_base) 314 | # define dispatch_event_add(t,c) event_add(&(c)->event, 0) 315 | # define is_listen_thread() 1 316 | # define item_from_freelist() do_item_from_freelist() 317 | # define item_add_to_freelist(x) do_item_add_to_freelist(x) 318 | # define thread_init(x,y) 0 319 | 320 | # define STATS_LOCK() /**/ 321 | # define STATS_UNLOCK() /**/ 322 | 323 | #endif /* !USE_THREADS */ 324 | 325 | extern int daemon_quit; 326 | -------------------------------------------------------------------------------- /missing: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Common stub for a few missing GNU programs while installing. 3 | 4 | scriptversion=2006-05-10.23 5 | 6 | # Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 7 | # Free Software Foundation, Inc. 8 | # Originally by Fran,cois Pinard , 1996. 9 | 10 | # This program is free software; you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation; either version 2, or (at your option) 13 | # any later version. 14 | 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program; if not, write to the Free Software 22 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 23 | # 02110-1301, USA. 24 | 25 | # As a special exception to the GNU General Public License, if you 26 | # distribute this file as part of a program that contains a 27 | # configuration script generated by Autoconf, you may include it under 28 | # the same distribution terms that you use for the rest of that program. 29 | 30 | if test $# -eq 0; then 31 | echo 1>&2 "Try \`$0 --help' for more information" 32 | exit 1 33 | fi 34 | 35 | run=: 36 | sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' 37 | sed_minuso='s/.* -o \([^ ]*\).*/\1/p' 38 | 39 | # In the cases where this matters, `missing' is being run in the 40 | # srcdir already. 41 | if test -f configure.ac; then 42 | configure_ac=configure.ac 43 | else 44 | configure_ac=configure.in 45 | fi 46 | 47 | msg="missing on your system" 48 | 49 | case $1 in 50 | --run) 51 | # Try to run requested program, and just exit if it succeeds. 52 | run= 53 | shift 54 | "$@" && exit 0 55 | # Exit code 63 means version mismatch. This often happens 56 | # when the user try to use an ancient version of a tool on 57 | # a file that requires a minimum version. In this case we 58 | # we should proceed has if the program had been absent, or 59 | # if --run hadn't been passed. 60 | if test $? = 63; then 61 | run=: 62 | msg="probably too old" 63 | fi 64 | ;; 65 | 66 | -h|--h|--he|--hel|--help) 67 | echo "\ 68 | $0 [OPTION]... PROGRAM [ARGUMENT]... 69 | 70 | Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an 71 | error status if there is no known handling for PROGRAM. 72 | 73 | Options: 74 | -h, --help display this help and exit 75 | -v, --version output version information and exit 76 | --run try to run the given command, and emulate it if it fails 77 | 78 | Supported PROGRAM values: 79 | aclocal touch file \`aclocal.m4' 80 | autoconf touch file \`configure' 81 | autoheader touch file \`config.h.in' 82 | autom4te touch the output file, or create a stub one 83 | automake touch all \`Makefile.in' files 84 | bison create \`y.tab.[ch]', if possible, from existing .[ch] 85 | flex create \`lex.yy.c', if possible, from existing .c 86 | help2man touch the output file 87 | lex create \`lex.yy.c', if possible, from existing .c 88 | makeinfo touch the output file 89 | tar try tar, gnutar, gtar, then tar without non-portable flags 90 | yacc create \`y.tab.[ch]', if possible, from existing .[ch] 91 | 92 | Send bug reports to ." 93 | exit $? 94 | ;; 95 | 96 | -v|--v|--ve|--ver|--vers|--versi|--versio|--version) 97 | echo "missing $scriptversion (GNU Automake)" 98 | exit $? 99 | ;; 100 | 101 | -*) 102 | echo 1>&2 "$0: Unknown \`$1' option" 103 | echo 1>&2 "Try \`$0 --help' for more information" 104 | exit 1 105 | ;; 106 | 107 | esac 108 | 109 | # Now exit if we have it, but it failed. Also exit now if we 110 | # don't have it and --version was passed (most likely to detect 111 | # the program). 112 | case $1 in 113 | lex|yacc) 114 | # Not GNU programs, they don't have --version. 115 | ;; 116 | 117 | tar) 118 | if test -n "$run"; then 119 | echo 1>&2 "ERROR: \`tar' requires --run" 120 | exit 1 121 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then 122 | exit 1 123 | fi 124 | ;; 125 | 126 | *) 127 | if test -z "$run" && ($1 --version) > /dev/null 2>&1; then 128 | # We have it, but it failed. 129 | exit 1 130 | elif test "x$2" = "x--version" || test "x$2" = "x--help"; then 131 | # Could not run --version or --help. This is probably someone 132 | # running `$TOOL --version' or `$TOOL --help' to check whether 133 | # $TOOL exists and not knowing $TOOL uses missing. 134 | exit 1 135 | fi 136 | ;; 137 | esac 138 | 139 | # If it does not exist, or fails to run (possibly an outdated version), 140 | # try to emulate it. 141 | case $1 in 142 | aclocal*) 143 | echo 1>&2 "\ 144 | WARNING: \`$1' is $msg. You should only need it if 145 | you modified \`acinclude.m4' or \`${configure_ac}'. You might want 146 | to install the \`Automake' and \`Perl' packages. Grab them from 147 | any GNU archive site." 148 | touch aclocal.m4 149 | ;; 150 | 151 | autoconf) 152 | echo 1>&2 "\ 153 | WARNING: \`$1' is $msg. You should only need it if 154 | you modified \`${configure_ac}'. You might want to install the 155 | \`Autoconf' and \`GNU m4' packages. Grab them from any GNU 156 | archive site." 157 | touch configure 158 | ;; 159 | 160 | autoheader) 161 | echo 1>&2 "\ 162 | WARNING: \`$1' is $msg. You should only need it if 163 | you modified \`acconfig.h' or \`${configure_ac}'. You might want 164 | to install the \`Autoconf' and \`GNU m4' packages. Grab them 165 | from any GNU archive site." 166 | files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` 167 | test -z "$files" && files="config.h" 168 | touch_files= 169 | for f in $files; do 170 | case $f in 171 | *:*) touch_files="$touch_files "`echo "$f" | 172 | sed -e 's/^[^:]*://' -e 's/:.*//'`;; 173 | *) touch_files="$touch_files $f.in";; 174 | esac 175 | done 176 | touch $touch_files 177 | ;; 178 | 179 | automake*) 180 | echo 1>&2 "\ 181 | WARNING: \`$1' is $msg. You should only need it if 182 | you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. 183 | You might want to install the \`Automake' and \`Perl' packages. 184 | Grab them from any GNU archive site." 185 | find . -type f -name Makefile.am -print | 186 | sed 's/\.am$/.in/' | 187 | while read f; do touch "$f"; done 188 | ;; 189 | 190 | autom4te) 191 | echo 1>&2 "\ 192 | WARNING: \`$1' is needed, but is $msg. 193 | You might have modified some files without having the 194 | proper tools for further handling them. 195 | You can get \`$1' as part of \`Autoconf' from any GNU 196 | archive site." 197 | 198 | file=`echo "$*" | sed -n "$sed_output"` 199 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 200 | if test -f "$file"; then 201 | touch $file 202 | else 203 | test -z "$file" || exec >$file 204 | echo "#! /bin/sh" 205 | echo "# Created by GNU Automake missing as a replacement of" 206 | echo "# $ $@" 207 | echo "exit 0" 208 | chmod +x $file 209 | exit 1 210 | fi 211 | ;; 212 | 213 | bison|yacc) 214 | echo 1>&2 "\ 215 | WARNING: \`$1' $msg. You should only need it if 216 | you modified a \`.y' file. You may need the \`Bison' package 217 | in order for those modifications to take effect. You can get 218 | \`Bison' from any GNU archive site." 219 | rm -f y.tab.c y.tab.h 220 | if test $# -ne 1; then 221 | eval LASTARG="\${$#}" 222 | case $LASTARG in 223 | *.y) 224 | SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` 225 | if test -f "$SRCFILE"; then 226 | cp "$SRCFILE" y.tab.c 227 | fi 228 | SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` 229 | if test -f "$SRCFILE"; then 230 | cp "$SRCFILE" y.tab.h 231 | fi 232 | ;; 233 | esac 234 | fi 235 | if test ! -f y.tab.h; then 236 | echo >y.tab.h 237 | fi 238 | if test ! -f y.tab.c; then 239 | echo 'main() { return 0; }' >y.tab.c 240 | fi 241 | ;; 242 | 243 | lex|flex) 244 | echo 1>&2 "\ 245 | WARNING: \`$1' is $msg. You should only need it if 246 | you modified a \`.l' file. You may need the \`Flex' package 247 | in order for those modifications to take effect. You can get 248 | \`Flex' from any GNU archive site." 249 | rm -f lex.yy.c 250 | if test $# -ne 1; then 251 | eval LASTARG="\${$#}" 252 | case $LASTARG in 253 | *.l) 254 | SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` 255 | if test -f "$SRCFILE"; then 256 | cp "$SRCFILE" lex.yy.c 257 | fi 258 | ;; 259 | esac 260 | fi 261 | if test ! -f lex.yy.c; then 262 | echo 'main() { return 0; }' >lex.yy.c 263 | fi 264 | ;; 265 | 266 | help2man) 267 | echo 1>&2 "\ 268 | WARNING: \`$1' is $msg. You should only need it if 269 | you modified a dependency of a manual page. You may need the 270 | \`Help2man' package in order for those modifications to take 271 | effect. You can get \`Help2man' from any GNU archive site." 272 | 273 | file=`echo "$*" | sed -n "$sed_output"` 274 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 275 | if test -f "$file"; then 276 | touch $file 277 | else 278 | test -z "$file" || exec >$file 279 | echo ".ab help2man is required to generate this page" 280 | exit 1 281 | fi 282 | ;; 283 | 284 | makeinfo) 285 | echo 1>&2 "\ 286 | WARNING: \`$1' is $msg. You should only need it if 287 | you modified a \`.texi' or \`.texinfo' file, or any other file 288 | indirectly affecting the aspect of the manual. The spurious 289 | call might also be the consequence of using a buggy \`make' (AIX, 290 | DU, IRIX). You might want to install the \`Texinfo' package or 291 | the \`GNU make' package. Grab either from any GNU archive site." 292 | # The file to touch is that specified with -o ... 293 | file=`echo "$*" | sed -n "$sed_output"` 294 | test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` 295 | if test -z "$file"; then 296 | # ... or it is the one specified with @setfilename ... 297 | infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` 298 | file=`sed -n ' 299 | /^@setfilename/{ 300 | s/.* \([^ ]*\) *$/\1/ 301 | p 302 | q 303 | }' $infile` 304 | # ... or it is derived from the source name (dir/f.texi becomes f.info) 305 | test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info 306 | fi 307 | # If the file does not exist, the user really needs makeinfo; 308 | # let's fail without touching anything. 309 | test -f $file || exit 1 310 | touch $file 311 | ;; 312 | 313 | tar) 314 | shift 315 | 316 | # We have already tried tar in the generic part. 317 | # Look for gnutar/gtar before invocation to avoid ugly error 318 | # messages. 319 | if (gnutar --version > /dev/null 2>&1); then 320 | gnutar "$@" && exit 0 321 | fi 322 | if (gtar --version > /dev/null 2>&1); then 323 | gtar "$@" && exit 0 324 | fi 325 | firstarg="$1" 326 | if shift; then 327 | case $firstarg in 328 | *o*) 329 | firstarg=`echo "$firstarg" | sed s/o//` 330 | tar "$firstarg" "$@" && exit 0 331 | ;; 332 | esac 333 | case $firstarg in 334 | *h*) 335 | firstarg=`echo "$firstarg" | sed s/h//` 336 | tar "$firstarg" "$@" && exit 0 337 | ;; 338 | esac 339 | fi 340 | 341 | echo 1>&2 "\ 342 | WARNING: I can't seem to be able to run \`tar' with the given arguments. 343 | You may want to install GNU tar or Free paxutils, or check the 344 | command line arguments." 345 | exit 1 346 | ;; 347 | 348 | *) 349 | echo 1>&2 "\ 350 | WARNING: \`$1' is needed, and is $msg. 351 | You might have modified some files without having the 352 | proper tools for further handling them. Check the \`README' file, 353 | it often tells you about the needed prerequisites for installing 354 | this package. You may also peek at any GNU archive site, in case 355 | some other package would contain this missing \`$1' program." 356 | exit 1 357 | ;; 358 | esac 359 | 360 | exit 0 361 | 362 | # Local variables: 363 | # eval: (add-hook 'write-file-hooks 'time-stamp) 364 | # time-stamp-start: "scriptversion=" 365 | # time-stamp-format: "%:y-%02m-%02d.%02H" 366 | # time-stamp-end: "$" 367 | # End: 368 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ./memcacheq -p 22201 -d -r -c 8000 -m 256 -H ./testenv -L 4096 -N -R -v > ./testenv.log 2>&1 4 | -------------------------------------------------------------------------------- /thread.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 | /* 3 | * MemcacheQ - Simple Queue Service over Memcache 4 | * 5 | * http://memcacheq.googlecode.com 6 | * 7 | * The source code of MemcacheQ is most based on MemcachDB: 8 | * 9 | * http://memcachedb.googlecode.com 10 | * 11 | * Copyright 2008 Steve Chu. All rights reserved. 12 | * 13 | * Use and distribution licensed under the BSD license. See 14 | * the LICENSE file for full text. 15 | * 16 | * Authors: 17 | * Steve Chu 18 | * 19 | */ 20 | 21 | #include "memcacheq.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #ifdef HAVE_MALLOC_H 28 | #include 29 | #endif 30 | 31 | #ifdef HAVE_STRING_H 32 | #include 33 | #endif 34 | 35 | #ifdef USE_THREADS 36 | 37 | #include 38 | 39 | #define ITEMS_PER_ALLOC 64 40 | 41 | /* An item in the connection queue. */ 42 | typedef struct conn_queue_item CQ_ITEM; 43 | struct conn_queue_item { 44 | int sfd; 45 | int init_state; 46 | int event_flags; 47 | int read_buffer_size; 48 | int is_udp; 49 | CQ_ITEM *next; 50 | }; 51 | 52 | /* A connection queue. */ 53 | typedef struct conn_queue CQ; 54 | struct conn_queue { 55 | CQ_ITEM *head; 56 | CQ_ITEM *tail; 57 | pthread_mutex_t lock; 58 | pthread_cond_t cond; 59 | }; 60 | 61 | /* Lock for connection freelist */ 62 | static pthread_mutex_t conn_lock; 63 | 64 | /* Lock for item buffer freelist */ 65 | static pthread_mutex_t ibuffer_lock; 66 | 67 | /* Lock for bdb */ 68 | static pthread_mutex_t bdb_lock; 69 | 70 | /* Lock for global stats */ 71 | static pthread_mutex_t stats_lock; 72 | 73 | /* Free list of CQ_ITEM structs */ 74 | static CQ_ITEM *cqi_freelist; 75 | static pthread_mutex_t cqi_freelist_lock; 76 | 77 | /* 78 | * Each libevent instance has a wakeup pipe, which other threads 79 | * can use to signal that they've put a new connection on its queue. 80 | */ 81 | typedef struct { 82 | pthread_t thread_id; /* unique ID of this thread */ 83 | struct event_base *base; /* libevent handle this thread uses */ 84 | struct event notify_event; /* listen event for notify pipe */ 85 | int notify_receive_fd; /* receiving end of notify pipe */ 86 | int notify_send_fd; /* sending end of notify pipe */ 87 | CQ new_conn_queue; /* queue of new connections to handle */ 88 | } LIBEVENT_THREAD; 89 | 90 | static LIBEVENT_THREAD *threads; 91 | 92 | /* 93 | * Number of threads that have finished setting themselves up. 94 | */ 95 | static int init_count = 0; 96 | static pthread_mutex_t init_lock; 97 | static pthread_cond_t init_cond; 98 | 99 | 100 | static void thread_libevent_process(int fd, short which, void *arg); 101 | 102 | /* 103 | * Initializes a connection queue. 104 | */ 105 | static void cq_init(CQ *cq) { 106 | pthread_mutex_init(&cq->lock, NULL); 107 | pthread_cond_init(&cq->cond, NULL); 108 | cq->head = NULL; 109 | cq->tail = NULL; 110 | } 111 | 112 | /* 113 | * Waits for work on a connection queue. 114 | */ 115 | static CQ_ITEM *cq_pop(CQ *cq) { 116 | CQ_ITEM *item; 117 | 118 | pthread_mutex_lock(&cq->lock); 119 | while (NULL == cq->head) 120 | pthread_cond_wait(&cq->cond, &cq->lock); 121 | item = cq->head; 122 | cq->head = item->next; 123 | if (NULL == cq->head) 124 | cq->tail = NULL; 125 | pthread_mutex_unlock(&cq->lock); 126 | 127 | return item; 128 | } 129 | 130 | /* 131 | * Looks for an item on a connection queue, but doesn't block if there isn't 132 | * one. 133 | * Returns the item, or NULL if no item is available 134 | */ 135 | static CQ_ITEM *cq_peek(CQ *cq) { 136 | CQ_ITEM *item; 137 | 138 | pthread_mutex_lock(&cq->lock); 139 | item = cq->head; 140 | if (NULL != item) { 141 | cq->head = item->next; 142 | if (NULL == cq->head) 143 | cq->tail = NULL; 144 | } 145 | pthread_mutex_unlock(&cq->lock); 146 | 147 | return item; 148 | } 149 | 150 | /* 151 | * Adds an item to a connection queue. 152 | */ 153 | static void cq_push(CQ *cq, CQ_ITEM *item) { 154 | item->next = NULL; 155 | 156 | pthread_mutex_lock(&cq->lock); 157 | if (NULL == cq->tail) 158 | cq->head = item; 159 | else 160 | cq->tail->next = item; 161 | cq->tail = item; 162 | pthread_cond_signal(&cq->cond); 163 | pthread_mutex_unlock(&cq->lock); 164 | } 165 | 166 | /* 167 | * Returns a fresh connection queue item. 168 | */ 169 | static CQ_ITEM *cqi_new() { 170 | CQ_ITEM *item = NULL; 171 | pthread_mutex_lock(&cqi_freelist_lock); 172 | if (cqi_freelist) { 173 | item = cqi_freelist; 174 | cqi_freelist = item->next; 175 | } 176 | pthread_mutex_unlock(&cqi_freelist_lock); 177 | 178 | if (NULL == item) { 179 | int i; 180 | 181 | /* Allocate a bunch of items at once to reduce fragmentation */ 182 | item = malloc(sizeof(CQ_ITEM) * ITEMS_PER_ALLOC); 183 | if (NULL == item) 184 | return NULL; 185 | 186 | /* 187 | * Link together all the new items except the first one 188 | * (which we'll return to the caller) for placement on 189 | * the freelist. 190 | */ 191 | for (i = 2; i < ITEMS_PER_ALLOC; i++) 192 | item[i - 1].next = &item[i]; 193 | 194 | pthread_mutex_lock(&cqi_freelist_lock); 195 | item[ITEMS_PER_ALLOC - 1].next = cqi_freelist; 196 | cqi_freelist = &item[1]; 197 | pthread_mutex_unlock(&cqi_freelist_lock); 198 | } 199 | 200 | return item; 201 | } 202 | 203 | 204 | /* 205 | * Frees a connection queue item (adds it to the freelist.) 206 | */ 207 | static void cqi_free(CQ_ITEM *item) { 208 | pthread_mutex_lock(&cqi_freelist_lock); 209 | item->next = cqi_freelist; 210 | cqi_freelist = item; 211 | pthread_mutex_unlock(&cqi_freelist_lock); 212 | } 213 | 214 | 215 | /* 216 | * Creates a worker thread. 217 | */ 218 | static void create_worker(void *(*func)(void *), void *arg) { 219 | pthread_t thread; 220 | pthread_attr_t attr; 221 | int ret; 222 | 223 | pthread_attr_init(&attr); 224 | 225 | if ((ret = pthread_create(&thread, &attr, func, arg)) != 0) { 226 | fprintf(stderr, "Can't create thread: %s\n", 227 | strerror(ret)); 228 | exit(1); 229 | } 230 | } 231 | 232 | 233 | /* 234 | * Pulls a conn structure from the freelist, if one is available. 235 | */ 236 | conn *mt_conn_from_freelist() { 237 | conn *c; 238 | 239 | pthread_mutex_lock(&conn_lock); 240 | c = do_conn_from_freelist(); 241 | pthread_mutex_unlock(&conn_lock); 242 | 243 | return c; 244 | } 245 | 246 | 247 | /* 248 | * Adds a conn structure to the freelist. 249 | * 250 | * Returns 0 on success, 1 if the structure couldn't be added. 251 | */ 252 | bool mt_conn_add_to_freelist(conn *c) { 253 | bool result; 254 | 255 | pthread_mutex_lock(&conn_lock); 256 | result = do_conn_add_to_freelist(c); 257 | pthread_mutex_unlock(&conn_lock); 258 | 259 | return result; 260 | } 261 | 262 | /* 263 | * Pulls a item buffer from the freelist, if one is available. 264 | */ 265 | 266 | item *mt_item_from_freelist(void) { 267 | item *it; 268 | pthread_mutex_lock(&ibuffer_lock); 269 | it = do_item_from_freelist(); 270 | pthread_mutex_unlock(&ibuffer_lock); 271 | return it; 272 | } 273 | 274 | /* 275 | * Adds a item buffer to the freelist. 276 | * 277 | * Returns 0 on success, 1 if the buffer couldn't be added. 278 | */ 279 | int mt_item_add_to_freelist(item *it){ 280 | int result; 281 | 282 | pthread_mutex_lock(&ibuffer_lock); 283 | result = do_item_add_to_freelist(it); 284 | pthread_mutex_unlock(&ibuffer_lock); 285 | 286 | return result; 287 | } 288 | 289 | 290 | /****************************** LIBEVENT THREADS *****************************/ 291 | 292 | /* 293 | * Set up a thread's information. 294 | */ 295 | static void setup_thread(LIBEVENT_THREAD *me) { 296 | if (! me->base) { 297 | me->base = event_init(); 298 | if (! me->base) { 299 | fprintf(stderr, "Can't allocate event base\n"); 300 | exit(1); 301 | } 302 | } 303 | 304 | /* Listen for notifications from other threads */ 305 | event_set(&me->notify_event, me->notify_receive_fd, 306 | EV_READ | EV_PERSIST, thread_libevent_process, me); 307 | event_base_set(me->base, &me->notify_event); 308 | 309 | if (event_add(&me->notify_event, 0) == -1) { 310 | fprintf(stderr, "Can't monitor libevent notify pipe\n"); 311 | exit(1); 312 | } 313 | 314 | cq_init(&me->new_conn_queue); 315 | } 316 | 317 | 318 | /* 319 | * Worker thread: main event loop 320 | */ 321 | static void *worker_libevent(void *arg) { 322 | LIBEVENT_THREAD *me = arg; 323 | 324 | /* Any per-thread setup can happen here; thread_init() will block until 325 | * all threads have finished initializing. 326 | */ 327 | 328 | pthread_mutex_lock(&init_lock); 329 | init_count++; 330 | pthread_cond_signal(&init_cond); 331 | pthread_mutex_unlock(&init_lock); 332 | 333 | event_base_loop(me->base, 0); 334 | return NULL; 335 | } 336 | 337 | 338 | /* 339 | * Processes an incoming "handle a new connection" item. This is called when 340 | * input arrives on the libevent wakeup pipe. 341 | */ 342 | static void thread_libevent_process(int fd, short which, void *arg) { 343 | LIBEVENT_THREAD *me = arg; 344 | CQ_ITEM *item; 345 | char buf[1]; 346 | 347 | if (read(fd, buf, 1) != 1) 348 | if (settings.verbose > 0) 349 | fprintf(stderr, "Can't read from libevent pipe\n"); 350 | 351 | item = cq_peek(&me->new_conn_queue); 352 | 353 | if (NULL != item) { 354 | conn *c = conn_new(item->sfd, item->init_state, item->event_flags, 355 | item->read_buffer_size, item->is_udp, me->base); 356 | if (c == NULL) { 357 | if (item->is_udp) { 358 | fprintf(stderr, "Can't listen for events on UDP socket\n"); 359 | exit(1); 360 | } else { 361 | if (settings.verbose > 0) { 362 | fprintf(stderr, "Can't listen for events on fd %d\n", 363 | item->sfd); 364 | } 365 | close(item->sfd); 366 | } 367 | } 368 | cqi_free(item); 369 | } 370 | } 371 | 372 | /* Which thread we assigned a connection to most recently. */ 373 | static int last_thread = -1; 374 | 375 | /* 376 | * Dispatches a new connection to another thread. This is only ever called 377 | * from the main thread, either during initialization (for UDP) or because 378 | * of an incoming connection. 379 | */ 380 | void dispatch_conn_new(int sfd, int init_state, int event_flags, 381 | int read_buffer_size, int is_udp) { 382 | CQ_ITEM *item = cqi_new(); 383 | int thread = (last_thread + 1) % settings.num_threads; 384 | 385 | last_thread = thread; 386 | 387 | item->sfd = sfd; 388 | item->init_state = init_state; 389 | item->event_flags = event_flags; 390 | item->read_buffer_size = read_buffer_size; 391 | item->is_udp = is_udp; 392 | 393 | cq_push(&threads[thread].new_conn_queue, item); 394 | if (write(threads[thread].notify_send_fd, "", 1) != 1) { 395 | perror("Writing to thread notify pipe"); 396 | } 397 | } 398 | 399 | /* 400 | * Returns true if this is the thread that listens for new TCP connections. 401 | */ 402 | int mt_is_listen_thread() { 403 | return pthread_self() == threads[0].thread_id; 404 | } 405 | 406 | /******************************* GLOBAL STATS ******************************/ 407 | 408 | void mt_stats_lock() { 409 | pthread_mutex_lock(&stats_lock); 410 | } 411 | 412 | void mt_stats_unlock() { 413 | pthread_mutex_unlock(&stats_lock); 414 | } 415 | 416 | /* 417 | * Initializes the thread subsystem, creating various worker threads. 418 | * 419 | * nthreads Number of event handler threads to spawn 420 | * main_base Event base for main thread 421 | */ 422 | void thread_init(int nthreads, struct event_base *main_base) { 423 | int i; 424 | 425 | pthread_mutex_init(&bdb_lock, NULL); 426 | pthread_mutex_init(&ibuffer_lock, NULL); 427 | pthread_mutex_init(&conn_lock, NULL); 428 | pthread_mutex_init(&stats_lock, NULL); 429 | 430 | pthread_mutex_init(&init_lock, NULL); 431 | pthread_cond_init(&init_cond, NULL); 432 | 433 | pthread_mutex_init(&cqi_freelist_lock, NULL); 434 | cqi_freelist = NULL; 435 | 436 | threads = malloc(sizeof(LIBEVENT_THREAD) * nthreads); 437 | if (! threads) { 438 | perror("Can't allocate thread descriptors"); 439 | exit(1); 440 | } 441 | 442 | threads[0].base = main_base; 443 | threads[0].thread_id = pthread_self(); 444 | 445 | for (i = 0; i < nthreads; i++) { 446 | int fds[2]; 447 | if (pipe(fds)) { 448 | perror("Can't create notify pipe"); 449 | exit(1); 450 | } 451 | 452 | threads[i].notify_receive_fd = fds[0]; 453 | threads[i].notify_send_fd = fds[1]; 454 | 455 | setup_thread(&threads[i]); 456 | } 457 | 458 | /* Create threads after we've done all the libevent setup. */ 459 | for (i = 1; i < nthreads; i++) { 460 | create_worker(worker_libevent, &threads[i]); 461 | } 462 | 463 | /* Wait for all the threads to set themselves up before returning. */ 464 | pthread_mutex_lock(&init_lock); 465 | init_count++; /* main thread */ 466 | while (init_count < nthreads) { 467 | pthread_cond_wait(&init_cond, &init_lock); 468 | } 469 | pthread_mutex_unlock(&init_lock); 470 | } 471 | 472 | #endif 473 | -------------------------------------------------------------------------------- /tools/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = *.py 2 | -------------------------------------------------------------------------------- /tools/Makefile.in: -------------------------------------------------------------------------------- 1 | # Makefile.in generated by automake 1.10 from Makefile.am. 2 | # @configure_input@ 3 | 4 | # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 5 | # 2003, 2004, 2005, 2006 Free Software Foundation, Inc. 6 | # This Makefile.in is free software; the Free Software Foundation 7 | # gives unlimited permission to copy and/or distribute it, 8 | # with or without modifications, as long as this notice is preserved. 9 | 10 | # This program is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY, to the extent permitted by law; without 12 | # even the implied warranty of MERCHANTABILITY or FITNESS FOR A 13 | # PARTICULAR PURPOSE. 14 | 15 | @SET_MAKE@ 16 | VPATH = @srcdir@ 17 | pkgdatadir = $(datadir)/@PACKAGE@ 18 | pkglibdir = $(libdir)/@PACKAGE@ 19 | pkgincludedir = $(includedir)/@PACKAGE@ 20 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd 21 | install_sh_DATA = $(install_sh) -c -m 644 22 | install_sh_PROGRAM = $(install_sh) -c 23 | install_sh_SCRIPT = $(install_sh) -c 24 | INSTALL_HEADER = $(INSTALL_DATA) 25 | transform = $(program_transform_name) 26 | NORMAL_INSTALL = : 27 | PRE_INSTALL = : 28 | POST_INSTALL = : 29 | NORMAL_UNINSTALL = : 30 | PRE_UNINSTALL = : 31 | POST_UNINSTALL = : 32 | subdir = tools 33 | DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in 34 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 35 | am__aclocal_m4_deps = $(top_srcdir)/configure.ac 36 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ 37 | $(ACLOCAL_M4) 38 | mkinstalldirs = $(install_sh) -d 39 | CONFIG_HEADER = $(top_builddir)/config.h 40 | CONFIG_CLEAN_FILES = 41 | SOURCES = 42 | DIST_SOURCES = 43 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) 44 | ACLOCAL = @ACLOCAL@ 45 | AMTAR = @AMTAR@ 46 | AUTOCONF = @AUTOCONF@ 47 | AUTOHEADER = @AUTOHEADER@ 48 | AUTOMAKE = @AUTOMAKE@ 49 | AWK = @AWK@ 50 | CC = @CC@ 51 | CCDEPMODE = @CCDEPMODE@ 52 | CFLAGS = @CFLAGS@ 53 | CPP = @CPP@ 54 | CPPFLAGS = @CPPFLAGS@ 55 | CYGPATH_W = @CYGPATH_W@ 56 | DEFS = @DEFS@ 57 | DEPDIR = @DEPDIR@ 58 | ECHO_C = @ECHO_C@ 59 | ECHO_N = @ECHO_N@ 60 | ECHO_T = @ECHO_T@ 61 | EGREP = @EGREP@ 62 | EXEEXT = @EXEEXT@ 63 | GREP = @GREP@ 64 | INSTALL = @INSTALL@ 65 | INSTALL_DATA = @INSTALL_DATA@ 66 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ 67 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ 68 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ 69 | LDFLAGS = @LDFLAGS@ 70 | LIBOBJS = @LIBOBJS@ 71 | LIBS = @LIBS@ 72 | LTLIBOBJS = @LTLIBOBJS@ 73 | MAKEINFO = @MAKEINFO@ 74 | MKDIR_P = @MKDIR_P@ 75 | OBJEXT = @OBJEXT@ 76 | PACKAGE = @PACKAGE@ 77 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ 78 | PACKAGE_NAME = @PACKAGE_NAME@ 79 | PACKAGE_STRING = @PACKAGE_STRING@ 80 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ 81 | PACKAGE_VERSION = @PACKAGE_VERSION@ 82 | PATH_SEPARATOR = @PATH_SEPARATOR@ 83 | SET_MAKE = @SET_MAKE@ 84 | SHELL = @SHELL@ 85 | STRIP = @STRIP@ 86 | VERSION = @VERSION@ 87 | abs_builddir = @abs_builddir@ 88 | abs_srcdir = @abs_srcdir@ 89 | abs_top_builddir = @abs_top_builddir@ 90 | abs_top_srcdir = @abs_top_srcdir@ 91 | ac_ct_CC = @ac_ct_CC@ 92 | am__include = @am__include@ 93 | am__leading_dot = @am__leading_dot@ 94 | am__quote = @am__quote@ 95 | am__tar = @am__tar@ 96 | am__untar = @am__untar@ 97 | bindir = @bindir@ 98 | build_alias = @build_alias@ 99 | builddir = @builddir@ 100 | datadir = @datadir@ 101 | datarootdir = @datarootdir@ 102 | docdir = @docdir@ 103 | dvidir = @dvidir@ 104 | exec_prefix = @exec_prefix@ 105 | host_alias = @host_alias@ 106 | htmldir = @htmldir@ 107 | includedir = @includedir@ 108 | infodir = @infodir@ 109 | install_sh = @install_sh@ 110 | libdir = @libdir@ 111 | libexecdir = @libexecdir@ 112 | localedir = @localedir@ 113 | localstatedir = @localstatedir@ 114 | mandir = @mandir@ 115 | mkdir_p = @mkdir_p@ 116 | oldincludedir = @oldincludedir@ 117 | pdfdir = @pdfdir@ 118 | prefix = @prefix@ 119 | program_transform_name = @program_transform_name@ 120 | psdir = @psdir@ 121 | sbindir = @sbindir@ 122 | sharedstatedir = @sharedstatedir@ 123 | srcdir = @srcdir@ 124 | sysconfdir = @sysconfdir@ 125 | target_alias = @target_alias@ 126 | top_builddir = @top_builddir@ 127 | top_srcdir = @top_srcdir@ 128 | EXTRA_DIST = *.py 129 | all: all-am 130 | 131 | .SUFFIXES: 132 | $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) 133 | @for dep in $?; do \ 134 | case '$(am__configure_deps)' in \ 135 | *$$dep*) \ 136 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \ 137 | && exit 0; \ 138 | exit 1;; \ 139 | esac; \ 140 | done; \ 141 | echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign tools/Makefile'; \ 142 | cd $(top_srcdir) && \ 143 | $(AUTOMAKE) --foreign tools/Makefile 144 | .PRECIOUS: Makefile 145 | Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status 146 | @case '$?' in \ 147 | *config.status*) \ 148 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ 149 | *) \ 150 | echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ 151 | cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ 152 | esac; 153 | 154 | $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) 155 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 156 | 157 | $(top_srcdir)/configure: $(am__configure_deps) 158 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 159 | $(ACLOCAL_M4): $(am__aclocal_m4_deps) 160 | cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh 161 | tags: TAGS 162 | TAGS: 163 | 164 | ctags: CTAGS 165 | CTAGS: 166 | 167 | 168 | distdir: $(DISTFILES) 169 | @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 170 | topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ 171 | list='$(DISTFILES)'; \ 172 | dist_files=`for file in $$list; do echo $$file; done | \ 173 | sed -e "s|^$$srcdirstrip/||;t" \ 174 | -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ 175 | case $$dist_files in \ 176 | */*) $(MKDIR_P) `echo "$$dist_files" | \ 177 | sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ 178 | sort -u` ;; \ 179 | esac; \ 180 | for file in $$dist_files; do \ 181 | if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ 182 | if test -d $$d/$$file; then \ 183 | dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ 184 | if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ 185 | cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ 186 | fi; \ 187 | cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ 188 | else \ 189 | test -f $(distdir)/$$file \ 190 | || cp -p $$d/$$file $(distdir)/$$file \ 191 | || exit 1; \ 192 | fi; \ 193 | done 194 | check-am: all-am 195 | check: check-am 196 | all-am: Makefile 197 | installdirs: 198 | install: install-am 199 | install-exec: install-exec-am 200 | install-data: install-data-am 201 | uninstall: uninstall-am 202 | 203 | install-am: all-am 204 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am 205 | 206 | installcheck: installcheck-am 207 | install-strip: 208 | $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ 209 | install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ 210 | `test -z '$(STRIP)' || \ 211 | echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install 212 | mostlyclean-generic: 213 | 214 | clean-generic: 215 | 216 | distclean-generic: 217 | -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) 218 | 219 | maintainer-clean-generic: 220 | @echo "This command is intended for maintainers to use" 221 | @echo "it deletes files that may require special tools to rebuild." 222 | clean: clean-am 223 | 224 | clean-am: clean-generic mostlyclean-am 225 | 226 | distclean: distclean-am 227 | -rm -f Makefile 228 | distclean-am: clean-am distclean-generic 229 | 230 | dvi: dvi-am 231 | 232 | dvi-am: 233 | 234 | html: html-am 235 | 236 | info: info-am 237 | 238 | info-am: 239 | 240 | install-data-am: 241 | 242 | install-dvi: install-dvi-am 243 | 244 | install-exec-am: 245 | 246 | install-html: install-html-am 247 | 248 | install-info: install-info-am 249 | 250 | install-man: 251 | 252 | install-pdf: install-pdf-am 253 | 254 | install-ps: install-ps-am 255 | 256 | installcheck-am: 257 | 258 | maintainer-clean: maintainer-clean-am 259 | -rm -f Makefile 260 | maintainer-clean-am: distclean-am maintainer-clean-generic 261 | 262 | mostlyclean: mostlyclean-am 263 | 264 | mostlyclean-am: mostlyclean-generic 265 | 266 | pdf: pdf-am 267 | 268 | pdf-am: 269 | 270 | ps: ps-am 271 | 272 | ps-am: 273 | 274 | uninstall-am: 275 | 276 | .MAKE: install-am install-strip 277 | 278 | .PHONY: all all-am check check-am clean clean-generic distclean \ 279 | distclean-generic distdir dvi dvi-am html html-am info info-am \ 280 | install install-am install-data install-data-am install-dvi \ 281 | install-dvi-am install-exec install-exec-am install-html \ 282 | install-html-am install-info install-info-am install-man \ 283 | install-pdf install-pdf-am install-ps install-ps-am \ 284 | install-strip installcheck installcheck-am installdirs \ 285 | maintainer-clean maintainer-clean-generic mostlyclean \ 286 | mostlyclean-generic pdf pdf-am ps ps-am uninstall uninstall-am 287 | 288 | # Tell versions [3.59,3.63) of GNU make to not export all variables. 289 | # Otherwise a system limit (for SysV at least) may be exceeded. 290 | .NOEXPORT: 291 | -------------------------------------------------------------------------------- /tools/mqpop.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright 2008 Steve Chu. All rights reserved. 5 | # 6 | # Use and distribution licensed under the BSD license. See 7 | # the LICENSE file for full text. 8 | # 9 | # Authors: 10 | # Steve Chu 11 | 12 | import memcache 13 | 14 | mc = memcache.Client(['127.0.0.1:22201'], debug=1) 15 | for i in range(100000): 16 | ret = mc.get("test1") 17 | assert(ret == "1234567890") 18 | print mc.get_stats("queue") 19 | mc.disconnect_all() 20 | -------------------------------------------------------------------------------- /tools/mqpush.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | # 4 | # Copyright 2008 Steve Chu. All rights reserved. 5 | # 6 | # Use and distribution licensed under the BSD license. See 7 | # the LICENSE file for full text. 8 | # 9 | # Authors: 10 | # Steve Chu 11 | 12 | import memcache 13 | 14 | mc = memcache.Client(['127.0.0.1:22201'], debug=1) 15 | for i in range(100000): 16 | mc.set("test1", "1234567890") 17 | print mc.get_stats("queue") 18 | mc.disconnect_all() 19 | --------------------------------------------------------------------------------