]> git.saurik.com Git - redis.git/commitdiff
Merge pull request #449 from ErikDubbelboer/unstable
authorSalvatore Sanfilippo <antirez@gmail.com>
Wed, 11 Apr 2012 16:25:44 +0000 (09:25 -0700)
committerSalvatore Sanfilippo <antirez@gmail.com>
Wed, 11 Apr 2012 16:25:44 +0000 (09:25 -0700)
added explanation for the magic 511 backlog number

19 files changed:
deps/Makefile
deps/linenoise/Makefile
redis.conf
src/Makefile
src/Makefile.dep [new file with mode: 0644]
src/cluster.c
src/config.c
src/config.h
src/crc64.c
src/memtest.c
src/rdb.c
src/rdb.h
src/redis.c
src/redis.h
src/rio.c
src/rio.h
src/version.h
tests/test_helper.tcl
tests/unit/limits.tcl [new file with mode: 0644]

index b881c814e7dbab036fe5fecb17057f460cf5194b..7cd9c0f64451bcc0262bf606627b76f969d0ad4c 100644 (file)
@@ -1,17 +1,6 @@
 # Redis dependency Makefile
 
-UNAME_S:=$(shell sh -c 'uname -s 2> /dev/null || echo not')
-
-LUA_CFLAGS=-O2 -Wall $(ARCH)
-ifeq ($(UNAME_S),SunOS)
-  # Make isinf() available
-  LUA_CFLAGS+= -D__C99FEATURES__=1
-endif
-
-JEMALLOC_CFLAGS=
-ifeq ($(ARCH),-m32)
-  JEMALLOC_CFLAGS+=CFLAGS="-std=gnu99 -Wall -pipe -g3 -fvisibility=hidden -O3 -funroll-loops -m32"
-endif
+uname_S:= $(shell sh -c 'uname -s 2>/dev/null || echo not')
 
 CCCOLOR="\033[34m"
 LINKCOLOR="\033[34;1m"
@@ -23,37 +12,67 @@ ENDCOLOR="\033[0m"
 default:
        @echo "Explicit target required"
 
-# Clean everything when ARCH is different
-ifneq ($(shell sh -c '[ -f .make-arch ] && cat .make-arch'), $(ARCH))
-.make-arch: distclean
-else
-.make-arch:
+.PHONY: default
+
+# Prerequisites target
+.make-prerequisites:
+       @touch $@
+
+# Clean everything when CFLAGS is different
+ifneq ($(shell sh -c '[ -f .make-cflags ] && cat .make-cflags || echo none'), $(CFLAGS))
+.make-cflags: distclean
+       -(echo "$(CFLAGS)" > .make-cflags)
+.make-prerequisites: .make-cflags
 endif
 
-.make-arch:
-       -(echo $(ARCH) > .make-arch)
+# Clean everything when LDFLAGS is different
+ifneq ($(shell sh -c '[ -f .make-ldflags ] && cat .make-ldflags || echo none'), $(LDFLAGS))
+.make-ldflags: distclean
+       -(echo "$(LDFLAGS)" > .make-ldflags)
+.make-prerequisites: .make-ldflags
+endif
 
 distclean:
        -(cd hiredis && $(MAKE) clean) > /dev/null || true
        -(cd linenoise && $(MAKE) clean) > /dev/null || true
        -(cd lua && $(MAKE) clean) > /dev/null || true
        -(cd jemalloc && [ -f Makefile ] && $(MAKE) distclean) > /dev/null || true
-       -(rm -f .make-arch)
+       -(rm -f .make-*)
+
+.PHONY: distclean
+
+hiredis: .make-prerequisites
+       @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
+       cd hiredis && $(MAKE) static
+
+.PHONY: hiredis
+
+linenoise: .make-prerequisites
+       @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
+       cd linenoise && $(MAKE)
+
+.PHONY: linenoise
+
+ifeq ($(uname_S),SunOS)
+  # Make isinf() available
+  LUA_CFLAGS= -D__C99FEATURES__=1
+endif
+
+LUA_CFLAGS+= -O2 -Wall -DLUA_ANSI $(CFLAGS)
+LUA_LDFLAGS+= $(LDFLAGS)
 
-hiredis: .make-arch
-       @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)hiredis$(ENDCOLOR)
-       cd hiredis && $(MAKE) static ARCH="$(ARCH)"
+lua: .make-prerequisites
+       @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
+       cd lua/src && $(MAKE) all CFLAGS="$(LUA_CFLAGS)" MYLDFLAGS="$(LUA_LDFLAGS)"
 
-linenoise: .make-arch
-       @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)linenoise$(ENDCOLOR)
-       cd linenoise && $(MAKE) ARCH="$(ARCH)"
+.PHONY: lua
 
-lua: .make-arch
-       @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)lua$(ENDCOLOR)
-       cd lua && $(MAKE) CFLAGS="$(LUA_CFLAGS)" MYLDFLAGS="$(ARCH)" ansi
+JEMALLOC_CFLAGS= -std=gnu99 -Wall -pipe -g3 -O3 -funroll-loops $(CFLAGS)
+JEMALLOC_LDFLAGS= $(LDFLAGS)
 
-jemalloc: .make-arch
-       @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)jemalloc$(ENDCOLOR)
-       cd jemalloc && ./configure $(JEMALLOC_CFLAGS) --with-jemalloc-prefix=je_ --enable-cc-silence && $(MAKE) lib/libjemalloc.a
+jemalloc: .make-prerequisites
+       @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
+       cd jemalloc && ./configure --with-jemalloc-prefix=je_ --enable-cc-silence CFLAGS="$(JEMALLOC_CFLAGS)" LDFLAGS="$(JEMALLOC_LDFLAGS)"
+       cd jemalloc && $(MAKE) lib/libjemalloc.a
 
-.PHONY: default conditional_clean hiredis linenoise lua jemalloc
+.PHONY: jemalloc
index 841f39072fff76ee6060581f0f264ecf8d5a6910..1dd894b49e9b992c8d9b22de75b30d21fcb63e81 100644 (file)
@@ -1,10 +1,21 @@
-linenoise_example: linenoise.h linenoise.c
+STD=
+WARN= -Wall
+OPT= -Os
+
+R_CFLAGS= $(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS)
+R_LDFLAGS= $(LDFLAGS)
+DEBUG= -g
+
+R_CC=$(CC) $(R_CFLAGS)
+R_LD=$(CC) $(R_LDFLAGS)
+
+linenoise.o: linenoise.h linenoise.c
 
 linenoise_example: linenoise.o example.o
-       $(CC) $(ARCH) -Wall -W -Os -g -o linenoise_example linenoise.o example.o
+       $(R_LD) -o $@ $^
 
 .c.o:
-       $(CC) $(ARCH) -c -Wall -W -Os -g $<
+       $(R_CC) -c $<
 
 clean:
        rm -f linenoise_example *.o
index 1b79e09efe1fde338145306304c96b922f0c4526..d7d293030e410b37c11ed77301de9add469b54ef 100644 (file)
@@ -114,6 +114,15 @@ stop-writes-on-bgsave-error yes
 # the dataset will likely be bigger if you have compressible values or keys.
 rdbcompression yes
 
+# Since verison 5 of RDB a CRC64 checksum is placed at the end of the file.
+# This makes the format more resistant to corruption but there is a performance
+# hit to pay (around 10%) when saving and loading RDB files, so you can disable it
+# for maximum performances.
+#
+# RDB files created with checksum disabled have a checksum of zero that will
+# tell the loading code to skip the check.
+rdbchecksum yes
+
 # The filename where to dump the DB
 dbfilename dump.rdb
 
index e94d03fd66b91d8d23397653a2ae52a6bd15bedb..656300d32cf2bbe6aec4af3912623720de4b48e4 100644 (file)
@@ -7,16 +7,25 @@ uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
 OPTIMIZATION?=-O2
 DEPENDENCY_TARGETS=hiredis linenoise lua
 
+STD= -std=c99 -pedantic
+WARN= -Wall
+OPT= $(OPTIMIZATION)
+
 ifeq ($(uname_S),SunOS)
-  CFLAGS?=-std=c99 -pedantic $(OPTIMIZATION) -Wall -W -D__EXTENSIONS__ -D_XPG6
-  CCLINK?=-ldl -lnsl -lsocket -lm -lpthread
-  DEBUG?=-g -ggdb 
+  R_CFLAGS= $(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS) -D__EXTENSIONS__ -D_XPG6
+  R_LDFLAGS= $(LDFLAGS)
+  R_LIBS= $(LIBS) -ldl -lnsl -lsocket -lm -lpthread
+  DEBUG= -g -ggdb
 else
-  CFLAGS?=-std=c99 -pedantic $(OPTIMIZATION) -Wall -W $(ARCH) $(PROF)
-  CCLINK?=-lm -pthread
-  DEBUG?=-g -rdynamic -ggdb 
+  R_CFLAGS= $(STD) $(WARN) $(OPT) $(DEBUG) $(CFLAGS)
+  R_LDFLAGS= $(LDFLAGS)
+  R_LIBS= $(LIBS) -lm -pthread
+  DEBUG= -g -rdynamic -ggdb
 endif
 
+# Include paths to dependencies
+R_CFLAGS+= -I../deps/hiredis -I../deps/linenoise -I../deps/lua/src
+
 # Default allocator
 ifeq ($(uname_S),Linux)
   MALLOC?=jemalloc
@@ -38,24 +47,23 @@ ifeq ($(USE_JEMALLOC),yes)
 endif
 
 ifeq ($(MALLOC),tcmalloc)
-  ALLOC_LINK=-ltcmalloc
-  ALLOC_FLAGS=-DUSE_TCMALLOC
+  R_CFLAGS+= -DUSE_TCMALLOC
+  R_LIBS+= -ltcmalloc
 endif
 
 ifeq ($(MALLOC),tcmalloc_minimal)
-  ALLOC_LINK=-ltcmalloc_minimal
-  ALLOC_FLAGS=-DUSE_TCMALLOC
+  R_CFLAGS+= -DUSE_TCMALLOC
+  R_LIBS+= -ltcmalloc_minimal
 endif
 
 ifeq ($(MALLOC),jemalloc)
-  ALLOC_LINK=../deps/jemalloc/lib/libjemalloc.a -ldl
-  ALLOC_FLAGS=-DUSE_JEMALLOC -I../deps/jemalloc/include
   DEPENDENCY_TARGETS+= jemalloc
+  R_CFLAGS+= -DUSE_JEMALLOC -I../deps/jemalloc/include
+  R_LIBS+= ../deps/jemalloc/lib/libjemalloc.a -ldl
 endif
 
-CCLINK+= $(ALLOC_LINK)
-CFLAGS+= $(ALLOC_FLAGS)
-CCOPT= $(CFLAGS) $(ARCH) $(PROF)
+R_CC=$(QUIET_CC)$(CC) $(R_CFLAGS)
+R_LD=$(QUIET_LINK)$(CC) $(R_LDFLAGS)
 
 PREFIX= /usr/local
 INSTALL_BIN= $(PREFIX)/bin
@@ -69,176 +77,100 @@ MAKECOLOR="\033[32;1m"
 ENDCOLOR="\033[0m"
 
 ifndef V
-QUIET_CC = @printf '    %b %b\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR);
-QUIET_LINK = @printf '    %b %b\n' $(LINKCOLOR)LINK$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR);
+QUIET_CC = @printf '    %b %b\n' $(CCCOLOR)CC$(ENDCOLOR) $(SRCCOLOR)$@$(ENDCOLOR) 1>&2;
+QUIET_LINK = @printf '    %b %b\n' $(LINKCOLOR)LINK$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR) 1>&2;
 endif
 
-OBJ = adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o
-BENCHOBJ = ae.o anet.o redis-benchmark.o sds.o adlist.o zmalloc.o
-CLIOBJ = anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o
-CHECKDUMPOBJ = redis-check-dump.o lzf_c.o lzf_d.o
-CHECKAOFOBJ = redis-check-aof.o
-
-PRGNAME = redis-server
-BENCHPRGNAME = redis-benchmark
-CLIPRGNAME = redis-cli
-CHECKDUMPPRGNAME = redis-check-dump
-CHECKAOFPRGNAME = redis-check-aof
-
-all: redis-benchmark redis-cli redis-check-dump redis-check-aof redis-server
+R_SERVER_NAME= redis-server
+R_SERVER_OBJ= adlist.o ae.o anet.o dict.o redis.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o crc16.o endianconv.o slowlog.o scripting.o bio.o rio.o rand.o memtest.o crc64.o
+R_CLI_NAME= redis-cli
+R_CLI_OBJ= anet.o sds.o adlist.o redis-cli.o zmalloc.o release.o
+R_BENCHMARK_NAME= redis-benchmark
+R_BENCHMARK_OBJ= ae.o anet.o redis-benchmark.o sds.o adlist.o zmalloc.o redis-benchmark.o
+R_CHECK_DUMP_NAME= redis-check-dump
+R_CHECK_DUMP_OBJ= redis-check-dump.o lzf_c.o lzf_d.o
+R_CHECK_AOF_NAME= redis-check-aof
+R_CHECK_AOF_OBJ= redis-check-aof.o
+
+all: $(R_SERVER_NAME) $(R_CLI_NAME) $(R_BENCHMARK_NAME) $(R_CHECK_DUMP_NAME) $(R_CHECK_AOF_NAME)
        @echo ""
        @echo "Hint: To run 'make test' is a good idea ;)"
        @echo ""
 
-# Deps (use make dep to generate this)
-adlist.o: adlist.c adlist.h zmalloc.h
-ae.o: ae.c ae.h zmalloc.h config.h ae_kqueue.c
-ae_epoll.o: ae_epoll.c
-ae_kqueue.o: ae_kqueue.c
-ae_select.o: ae_select.c
-anet.o: anet.c fmacros.h anet.h
-aof.o: aof.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h bio.h
-bio.o: bio.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h bio.h
-cluster.o: cluster.c redis.h fmacros.h config.h ae.h sds.h dict.h \
-  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h \
-  rio.h
-config.o: config.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h
-crc16.o: crc16.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h
-db.o: db.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h
-debug.o: debug.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h sha1.h
-dict.o: dict.c fmacros.h dict.h zmalloc.h
-endianconv.o: endianconv.c
-intset.o: intset.c intset.h zmalloc.h endianconv.h
-lzf_c.o: lzf_c.c lzfP.h
-lzf_d.o: lzf_d.c lzfP.h
-multi.o: multi.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h
-networking.o: networking.c redis.h fmacros.h config.h ae.h sds.h dict.h \
-  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h \
-  rio.h
-object.o: object.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h
-pqsort.o: pqsort.c
-pubsub.o: pubsub.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h
-rand.o: rand.c
-rdb.o: rdb.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h lzf.h \
-  zipmap.h
-redis-benchmark.o: redis-benchmark.c fmacros.h ae.h \
-  ../deps/hiredis/hiredis.h sds.h adlist.h zmalloc.h
-redis-check-aof.o: redis-check-aof.c fmacros.h config.h
-redis-check-dump.o: redis-check-dump.c lzf.h
-redis-cli.o: redis-cli.c fmacros.h version.h ../deps/hiredis/hiredis.h \
-  sds.h zmalloc.h ../deps/linenoise/linenoise.h help.h
-redis.o: redis.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h \
-  slowlog.h bio.h asciilogo.h
-release.o: release.c release.h
-replication.o: replication.c redis.h fmacros.h config.h ae.h sds.h dict.h \
-  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h \
-  rio.h
-rio.o: rio.c fmacros.h rio.h sds.h util.h
-scripting.o: scripting.c redis.h fmacros.h config.h ae.h sds.h dict.h \
-  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h \
-  rio.h sha1.h rand.h
-sds.o: sds.c sds.h zmalloc.h
-sha1.o: sha1.c sha1.h config.h
-slowlog.o: slowlog.c redis.h fmacros.h config.h ae.h sds.h dict.h \
-  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h \
-  rio.h slowlog.h
-sort.o: sort.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h \
-  pqsort.h
-syncio.o: syncio.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h
-t_hash.o: t_hash.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h
-t_list.o: t_list.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h
-t_set.o: t_set.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h
-t_string.o: t_string.c redis.h fmacros.h config.h ae.h sds.h dict.h \
-  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h \
-  rio.h
-t_zset.o: t_zset.c redis.h fmacros.h config.h ae.h sds.h dict.h adlist.h \
-  zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h rio.h
-util.o: util.c fmacros.h util.h
-ziplist.o: ziplist.c zmalloc.h util.h ziplist.h endianconv.h
-zipmap.o: zipmap.c zmalloc.h endianconv.h
-zmalloc.o: zmalloc.c config.h zmalloc.h
-
-# Clean local objects when ARCH is different
-ifneq ($(shell sh -c '[ -f .make-arch ] && cat .make-arch'), $(ARCH))
-.make-arch: clean
-else
-.make-arch:
-endif
+.PHONY: all
 
-.make-arch:
-       -(cd ../deps && $(MAKE) $(DEPENDENCY_TARGETS) ARCH="$(ARCH)")
-       -(echo $(ARCH) > .make-arch)
+# Deps (use make dep to generate this)
+include Makefile.dep
 
-# Clean local objects when allocator changes
-ifneq ($(shell sh -c '[ -f .make-malloc ] && cat .make-malloc'), $(MALLOC))
-.make-malloc: clean
-else
-.make-malloc:
-endif
+dep:
+       $(R_CC) -MM *.c > Makefile.dep
 
-.make-malloc:
-       -(echo $(MALLOC) > .make-malloc)
+.PHONY: dep
 
-# Union of make-prerequisites
-.make-prerequisites: .make-arch .make-malloc
+# Prerequisites target
+.make-prerequisites:
        @touch $@
 
-redis-server: .make-prerequisites $(OBJ)
-       $(QUIET_LINK)$(CC) -o $(PRGNAME) $(CCOPT) $(DEBUG) $(OBJ) ../deps/lua/src/liblua.a $(CCLINK)
+# Clean local objects and build dependencies when R_CFLAGS is different
+ifneq ($(shell sh -c '[ -f .make-cflags ] && cat .make-cflags || echo none'), $(R_CFLAGS))
+.make-cflags: clean
+       -(cd ../deps && $(MAKE) $(DEPENDENCY_TARGETS))
+       -(echo "$(R_CFLAGS)" > .make-cflags)
+.make-prerequisites: .make-cflags
+endif
 
-redis-benchmark: .make-prerequisites $(BENCHOBJ)
-       $(QUIET_LINK)$(CC) -o $(BENCHPRGNAME) $(CCOPT) $(DEBUG) $(BENCHOBJ) ../deps/hiredis/libhiredis.a $(CCLINK)
+# Clean local objects when R_LDFLAGS is different
+ifneq ($(shell sh -c '[ -f .make-ldflags ] && cat .make-ldflags || echo none'), $(R_LDFLAGS))
+.make-ldflags: clean
+       -(echo "$(R_LDFLAGS)" > .make-ldflags)
+.make-prerequisites: .make-ldflags
+endif
+
+# Clean local objects when MALLOC is different
+ifneq ($(shell sh -c '[ -f .make-malloc ] && cat .make-malloc || echo none'), $(MALLOC))
+.make-malloc: clean
+       -(echo "$(MALLOC)" > .make-malloc)
+.make-prerequisites: .make-malloc
+endif
 
-redis-benchmark.o: redis-benchmark.c .make-prerequisites
-       $(QUIET_CC)$(CC) -c $(CFLAGS) -I../deps/hiredis $(DEBUG) $(COMPILE_TIME) $<
+# redis-server
+$(R_SERVER_NAME): $(R_SERVER_OBJ)
+       $(R_LD) -o $@ $^ ../deps/lua/src/liblua.a $(R_LIBS)
 
-redis-cli: .make-prerequisites $(CLIOBJ)
-       $(QUIET_LINK)$(CC) -o $(CLIPRGNAME) $(CCOPT) $(DEBUG) $(CLIOBJ) ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(CCLINK)
+# redis-cli
+$(R_CLI_NAME): $(R_CLI_OBJ)
+       $(R_LD) -o $@ $^ ../deps/hiredis/libhiredis.a ../deps/linenoise/linenoise.o $(R_LIBS)
 
-redis-cli.o: redis-cli.c .make-prerequisites
-       $(QUIET_CC)$(CC) -c $(CFLAGS) -I../deps/hiredis -I../deps/linenoise $(DEBUG) $(COMPILE_TIME) $<
+# redis-benchmark
+$(R_BENCHMARK_NAME): $(R_BENCHMARK_OBJ)
+       $(R_LD) -o $@ $^ ../deps/hiredis/libhiredis.a $(R_LIBS)
 
-redis-check-dump: .make-prerequisites $(CHECKDUMPOBJ)
-       $(QUIET_LINK)$(CC) -o $(CHECKDUMPPRGNAME) $(CCOPT) $(DEBUG) $(CHECKDUMPOBJ) $(CCLINK)
+# redis-check-dump
+$(R_CHECK_DUMP_NAME): $(R_CHECK_DUMP_OBJ)
+       $(R_LD) -o $@ $^ $(R_LIBS)
 
-redis-check-aof: .make-prerequisites $(CHECKAOFOBJ)
-       $(QUIET_LINK)$(CC) -o $(CHECKAOFPRGNAME) $(CCOPT) $(DEBUG) $(CHECKAOFOBJ) $(CCLINK)
+# redis-check-aof
+$(R_CHECK_AOF_NAME): $(R_CHECK_AOF_OBJ)
+       $(R_LD) -o $@ $^ $(R_LIBS)
 
-# Because the jemalloc.h header is generated as a part of the jemalloc build
-# process, building it should complete before building any other object. Instead of
-# depending on a single artifact, simply build all dependencies first.
+# Because the jemalloc.h header is generated as a part of the jemalloc build,
+# building it should complete before building any other object. Instead of
+# depending on a single artifact, build all dependencies first.
 %.o: %.c .make-prerequisites
-       $(QUIET_CC)$(CC) -c $(CFLAGS) $(DEBUG) $(COMPILE_TIME) -I../deps/lua/src $<
-
-.PHONY: all clean distclean lcov
+       $(R_CC) -c $<
 
 clean:
-       rm -rf $(PRGNAME) $(BENCHPRGNAME) $(CLIPRGNAME) $(CHECKDUMPPRGNAME) $(CHECKAOFPRGNAME) *.o *.gcda *.gcno *.gcov redis.info lcov-html
+       rm -rf $(R_SERVER_NAME) $(R_CLI_NAME) $(R_BENCHMARK_NAME) $(R_CHECK_DUMP_NAME) $(R_CHECK_AOF_NAME) *.o *.gcda *.gcno *.gcov redis.info lcov-html
+
+.PHONY: clean
 
 distclean: clean
        -(cd ../deps && $(MAKE) distclean)
-       -(rm -f .make-arch .make-malloc)
+       -(rm -f .make-*)
 
-dep:
-       $(CC) -MM *.c -I ../deps/hiredis -I ../deps/linenoise
+.PHONY: distclean
 
-test: redis-server redis-check-aof
+test: $(R_SERVER_NAME) $(R_CHECK_AOF_NAME)
        @(cd ..; ./runtest)
 
 lcov:
@@ -247,8 +179,10 @@ lcov:
        @geninfo -o redis.info .
        @genhtml --legend -o lcov-html redis.info
 
-bench:
-       ./redis-benchmark
+.PHONY: lcov
+
+bench: $(R_BENCHMARK_NAME)
+       ./$(R_BENCHMARK_NAME)
 
 log:
        git log '--pretty=format:%ad %s (%cn)' --date=short > ../Changelog
@@ -257,27 +191,27 @@ log:
        @echo ""
        @echo "WARNING: if it fails under Linux you probably need to install libc6-dev-i386"
        @echo ""
-       $(MAKE) ARCH="-m32" JEMALLOC_CFLAGS='CFLAGS="-std=gnu99 -Wall -pipe -g3 -fvisibility=hidden -O3 -funroll-loops -m32"'
+       $(MAKE) CFLAGS="$(CFLAGS) -m32" LDFLAGS="$(LDFLAGS) -m32"
 
 gprof:
-       $(MAKE) PROF="-pg"
+       $(MAKE) CFLAGS="$(CFLAGS) -pg" LDFLAGS="$(LDFLAGS) -pg"
 
 gcov:
-       $(MAKE) PROF="-fprofile-arcs -ftest-coverage -DCOVERAGE_TEST"
+       $(MAKE) CFLAGS="$(CFLAGS) -fprofile-arcs -ftest-coverage -DCOVERAGE_TEST"
 
 noopt:
-       $(MAKE) OPTIMIZATION=""
+       $(MAKE) OPT="-O0"
 
 32bitgprof:
-       $(MAKE) PROF="-pg" ARCH="-arch i386"
+       $(MAKE) CFLAGS="$(CFLAGS) -m32" LDFLAGS="$(LDFLAGS) -m32" gprof
 
 src/help.h:
        @../utils/generate-command-help.rb > help.h
 
 install: all
        mkdir -p $(INSTALL_BIN)
-       $(INSTALL) $(PRGNAME) $(INSTALL_BIN)
-       $(INSTALL) $(BENCHPRGNAME) $(INSTALL_BIN)
-       $(INSTALL) $(CLIPRGNAME) $(INSTALL_BIN)
-       $(INSTALL) $(CHECKDUMPPRGNAME) $(INSTALL_BIN)
-       $(INSTALL) $(CHECKAOFPRGNAME) $(INSTALL_BIN)
+       $(INSTALL) $(R_SERVER_NAME) $(INSTALL_BIN)
+       $(INSTALL) $(R_BENCHMARK_NAME) $(INSTALL_BIN)
+       $(INSTALL) $(R_CLI_NAME) $(INSTALL_BIN)
+       $(INSTALL) $(R_CHECK_DUMP_NAME) $(INSTALL_BIN)
+       $(INSTALL) $(R_CHECK_AOF_NAME) $(INSTALL_BIN)
diff --git a/src/Makefile.dep b/src/Makefile.dep
new file mode 100644 (file)
index 0000000..d0254e8
--- /dev/null
@@ -0,0 +1,104 @@
+adlist.o: adlist.c adlist.h zmalloc.h
+ae.o: ae.c ae.h zmalloc.h config.h ae_kqueue.c
+ae_epoll.o: ae_epoll.c
+ae_kqueue.o: ae_kqueue.c
+ae_select.o: ae_select.c
+anet.o: anet.c fmacros.h anet.h
+aof.o: aof.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h bio.h
+bio.o: bio.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h bio.h
+cluster.o: cluster.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h endianconv.h
+config.o: config.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h
+crc16.o: crc16.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h
+crc64.o: crc64.c
+db.o: db.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h
+debug.o: debug.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h sha1.h
+dict.o: dict.c fmacros.h dict.h zmalloc.h
+endianconv.o: endianconv.c
+intset.o: intset.c intset.h zmalloc.h endianconv.h
+lzf_c.o: lzf_c.c lzfP.h
+lzf_d.o: lzf_d.c lzfP.h
+memtest.o: memtest.c
+multi.o: multi.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h
+networking.o: networking.c redis.h fmacros.h config.h \
+  ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \
+  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h \
+  rio.h
+object.o: object.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h
+pqsort.o: pqsort.c
+pubsub.o: pubsub.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h
+rand.o: rand.c
+rdb.o: rdb.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h lzf.h zipmap.h \
+  endianconv.h
+redis-benchmark.o: redis-benchmark.c fmacros.h ae.h \
+  ../deps/hiredis/hiredis.h sds.h adlist.h zmalloc.h
+redis-check-aof.o: redis-check-aof.c fmacros.h config.h
+redis-check-dump.o: redis-check-dump.c lzf.h
+redis-cli.o: redis-cli.c fmacros.h version.h ../deps/hiredis/hiredis.h \
+  sds.h zmalloc.h ../deps/linenoise/linenoise.h help.h
+redis.o: redis.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h slowlog.h bio.h \
+  asciilogo.h
+release.o: release.c release.h
+replication.o: replication.c redis.h fmacros.h config.h \
+  ../deps/lua/src/lua.h ../deps/lua/src/luaconf.h ae.h sds.h dict.h \
+  adlist.h zmalloc.h anet.h ziplist.h intset.h version.h util.h rdb.h \
+  rio.h
+rio.o: rio.c fmacros.h rio.h sds.h util.h
+scripting.o: scripting.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h sha1.h rand.h \
+  ../deps/lua/src/lauxlib.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/lualib.h
+sds.o: sds.c sds.h zmalloc.h
+sha1.o: sha1.c sha1.h config.h
+slowlog.o: slowlog.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h slowlog.h
+sort.o: sort.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h pqsort.h
+syncio.o: syncio.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h
+t_hash.o: t_hash.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h
+t_list.o: t_list.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h
+t_set.o: t_set.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h
+t_string.o: t_string.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h
+t_zset.o: t_zset.c redis.h fmacros.h config.h ../deps/lua/src/lua.h \
+  ../deps/lua/src/luaconf.h ae.h sds.h dict.h adlist.h zmalloc.h anet.h \
+  ziplist.h intset.h version.h util.h rdb.h rio.h
+util.o: util.c fmacros.h util.h
+ziplist.o: ziplist.c zmalloc.h util.h ziplist.h endianconv.h
+zipmap.o: zipmap.c zmalloc.h endianconv.h
+zmalloc.o: zmalloc.c config.h zmalloc.h
index 8cd20c84d740c9e1686d5b71f2ab2be55f8fb70d..93f095c34828fe84a66dc3f4e8fefcf27630ff44 100644 (file)
@@ -1486,7 +1486,7 @@ void createDumpPayload(rio *payload, robj *o) {
     payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,buf,2);
 
     /* CRC64 */
-    crc = crc64((unsigned char*)payload->io.buffer.ptr,
+    crc = crc64(0,(unsigned char*)payload->io.buffer.ptr,
                 sdslen(payload->io.buffer.ptr));
     memrev64ifbe(&crc);
     payload->io.buffer.ptr = sdscatlen(payload->io.buffer.ptr,&crc,8);
@@ -1510,7 +1510,7 @@ int verifyDumpPayload(unsigned char *p, size_t len) {
     if (rdbver != REDIS_RDB_VERSION) return REDIS_ERR;
 
     /* Verify CRC64 */
-    crc = crc64(p,len-8);
+    crc = crc64(0,p,len-8);
     memrev64ifbe(&crc);
     return (memcmp(&crc,footer+2,8) == 0) ? REDIS_OK : REDIS_ERR;
 }
@@ -1586,7 +1586,7 @@ void migrateCommand(redisClient *c) {
     int fd;
     long timeout;
     long dbid;
-    long long ttl, expireat;
+    long long ttl = 0, expireat;
     robj *o;
     rio cmd, payload;
 
@@ -1633,7 +1633,7 @@ void migrateCommand(redisClient *c) {
     redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,"RESTORE",7));
     redisAssertWithInfo(c,NULL,c->argv[3]->encoding == REDIS_ENCODING_RAW);
     redisAssertWithInfo(c,NULL,rioWriteBulkString(&cmd,c->argv[3]->ptr,sdslen(c->argv[3]->ptr)));
-    redisAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,(expireat==-1) ? 0 : ttl));
+    redisAssertWithInfo(c,NULL,rioWriteBulkLongLong(&cmd,ttl));
 
     /* Finally the last argument that is the serailized object payload
      * in the DUMP format. */
index 8dffe28873d509ab50fc6d5ca1f98301502e270a..9899dfbcba2bb748484aa05fd5ae015c0da9217c 100644 (file)
@@ -210,6 +210,10 @@ void loadServerConfigFromString(char *config) {
             if ((server.rdb_compression = yesnotoi(argv[1])) == -1) {
                 err = "argument must be 'yes' or 'no'"; goto loaderr;
             }
+        } else if (!strcasecmp(argv[0],"rdbchecksum") && argc == 2) {
+            if ((server.rdb_checksum = yesnotoi(argv[1])) == -1) {
+                err = "argument must be 'yes' or 'no'"; goto loaderr;
+            }
         } else if (!strcasecmp(argv[0],"activerehashing") && argc == 2) {
             if ((server.activerehashing = yesnotoi(argv[1])) == -1) {
                 err = "argument must be 'yes' or 'no'"; goto loaderr;
@@ -633,6 +637,16 @@ void configSetCommand(redisClient *c) {
             enableWatchdog(ll);
         else
             disableWatchdog();
+    } else if (!strcasecmp(c->argv[2]->ptr,"rdbcompression")) {
+        int yn = yesnotoi(o->ptr);
+
+        if (yn == -1) goto badfmt;
+        server.rdb_compression = yn;
+    } else if (!strcasecmp(c->argv[2]->ptr,"rdbchecksum")) {
+        int yn = yesnotoi(o->ptr);
+
+        if (yn == -1) goto badfmt;
+        server.rdb_checksum = yn;
     } else {
         addReplyErrorFormat(c,"Unsupported CONFIG parameter: %s",
             (char*)c->argv[2]->ptr);
@@ -734,6 +748,7 @@ void configGetCommand(redisClient *c) {
             server.stop_writes_on_bgsave_err);
     config_get_bool_field("daemonize", server.daemonize);
     config_get_bool_field("rdbcompression", server.rdb_compression);
+    config_get_bool_field("rdbchecksum", server.rdb_checksum);
     config_get_bool_field("activerehashing", server.activerehashing);
 
     /* Everything we can't handle with macros follows. */
index 6a69364a97158a2d7f46b82449046dadb200a9f2..136fd40c4c8eda0f89e975814de4127652c48ae8 100644 (file)
 #define        BIG_ENDIAN      4321    /* most-significant byte first (IBM, net) */
 #define        PDP_ENDIAN      3412    /* LSB first in word, MSW first in long (pdp)*/
 
-#if defined(vax) || defined(ns32000) || defined(sun386) || defined(__i386__) || \
-    defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \
-    defined(__alpha__) || defined(__alpha)
-#define BYTE_ORDER     LITTLE_ENDIAN
+#if defined(__i386__) || defined(__x86_64__) || defined(__amd64__) || \
+   defined(vax) || defined(ns32000) || defined(sun386) || \
+   defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \
+   defined(__alpha__) || defined(__alpha)
+#define BYTE_ORDER    LITTLE_ENDIAN
 #endif
 
 #if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \
index f2ea8d4ae4cd18b389b920963e6494d206e7bdbd..ecdba90e0452ee5bc0cf3da77ab4277fe0e409ba 100644 (file)
@@ -170,8 +170,7 @@ static const uint64_t crc64_tab[256] = {
     UINT64_C(0x536fa08fdfd90e51), UINT64_C(0x29b7d047efec8728),
 };
 
-uint64_t crc64(const unsigned char *s, uint64_t l) {
-    uint64_t crc = 0;
+uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l) {
     uint64_t j;
 
     for (j = 0; j < l; j++) {
@@ -186,7 +185,7 @@ uint64_t crc64(const unsigned char *s, uint64_t l) {
 #include <stdio.h>
 int main(void) {
     printf("e9c6d914c4b8d9ca == %016llx\n",
-        (unsigned long long) crc64((unsigned char*)"123456789",9));
+        (unsigned long long) crc64(0,(unsigned char*)"123456789",9));
     return 0;
 }
 #endif
index 272ec502255527207afd27af952b222df5f10a24..c8b47d489a34b72234a79ea678f539c7c3280bf3 100644 (file)
 #endif
 
 #ifdef MEMTEST_32BIT
-#define ULONG_ONEZERO 0xaaaaaaaaaaaaaaaaUL
-#define ULONG_ZEROONE 0x5555555555555555UL
-#else
 #define ULONG_ONEZERO 0xaaaaaaaaUL
 #define ULONG_ZEROONE 0x55555555UL
+#else
+#define ULONG_ONEZERO 0xaaaaaaaaaaaaaaaaUL
+#define ULONG_ZEROONE 0x5555555555555555UL
 #endif
 
 static struct winsize ws;
index abb966e0281be1ca94581665d71b2b404ed26fab..8ffd2c28f9d331f864d6aeb3be18ff50bc0b8fe3 100644 (file)
--- a/src/rdb.c
+++ b/src/rdb.c
@@ -1,6 +1,7 @@
 #include "redis.h"
 #include "lzf.h"    /* LZF compression library */
 #include "zipmap.h"
+#include "endianconv.h"
 
 #include <math.h>
 #include <sys/types.h>
@@ -602,6 +603,7 @@ int rdbSave(char *filename) {
     long long now = mstime();
     FILE *fp;
     rio rdb;
+    uint64_t cksum;
 
     snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());
     fp = fopen(tmpfile,"w");
@@ -612,6 +614,8 @@ int rdbSave(char *filename) {
     }
 
     rioInitWithFile(&rdb,fp);
+    if (server.rdb_checksum)
+        rdb.update_cksum = rioGenericUpdateChecksum;
     snprintf(magic,sizeof(magic),"REDIS%04d",REDIS_RDB_VERSION);
     if (rdbWriteRaw(&rdb,magic,9) == -1) goto werr;
 
@@ -641,9 +645,17 @@ int rdbSave(char *filename) {
         }
         dictReleaseIterator(di);
     }
+    di = NULL; /* So that we don't release it again on error. */
+
     /* EOF opcode */
     if (rdbSaveType(&rdb,REDIS_RDB_OPCODE_EOF) == -1) goto werr;
 
+    /* CRC64 checksum. It will be zero if checksum computation is disabled, the
+     * loading code skips the check in this case. */
+    cksum = rdb.cksum;
+    memrev64ifbe(&cksum);
+    rioWrite(&rdb,&cksum,8);
+
     /* Make sure data will not remain on the OS's output buffers */
     fflush(fp);
     fsync(fileno(fp));
@@ -717,7 +729,7 @@ robj *rdbLoadObject(int rdbtype, rio *rdb) {
     size_t len;
     unsigned int i;
 
-    redisLog(REDIS_DEBUG,"LOADING OBJECT %d (at %d)\n",rdbtype,rdb->tell(rdb));
+    redisLog(REDIS_DEBUG,"LOADING OBJECT %d (at %d)\n",rdbtype,rioTell(rdb));
     if (rdbtype == REDIS_RDB_TYPE_STRING) {
         /* Read string value */
         if ((o = rdbLoadEncodedStringObject(rdb)) == NULL) return NULL;
@@ -1016,6 +1028,8 @@ int rdbLoad(char *filename) {
         return REDIS_ERR;
     }
     rioInitWithFile(&rdb,fp);
+    if (server.rdb_checksum)
+        rdb.update_cksum = rioGenericUpdateChecksum;
     if (rioRead(&rdb,buf,9) == 0) goto eoferr;
     buf[9] = '\0';
     if (memcmp(buf,"REDIS",5) != 0) {
@@ -1025,7 +1039,7 @@ int rdbLoad(char *filename) {
         return REDIS_ERR;
     }
     rdbver = atoi(buf+5);
-    if (rdbver < 1 || rdbver > 4) {
+    if (rdbver < 1 || rdbver > 5) {
         fclose(fp);
         redisLog(REDIS_WARNING,"Can't handle RDB format version %d",rdbver);
         errno = EINVAL;
@@ -1039,7 +1053,7 @@ int rdbLoad(char *filename) {
 
         /* Serve the clients from time to time */
         if (!(loops++ % 1000)) {
-            loadingProgress(rdb.tell(&rdb));
+            loadingProgress(rioTell(&rdb));
             aeProcessEvents(server.el, AE_FILE_EVENTS|AE_DONT_WAIT);
         }
 
@@ -1096,6 +1110,20 @@ int rdbLoad(char *filename) {
 
         decrRefCount(key);
     }
+    /* Verify the checksum if RDB version is >= 5 */
+    if (rdbver >= 5 && server.rdb_checksum) {
+        uint64_t cksum, expected = rdb.cksum;
+
+        if (rioRead(&rdb,&cksum,8) == 0) goto eoferr;
+        memrev64ifbe(&cksum);
+        if (cksum == 0) {
+            redisLog(REDIS_WARNING,"RDB file was saved with checksum disabled: no check performed.");
+        } else if (cksum != expected) {
+            redisLog(REDIS_WARNING,"Wrong RDB checksum. Aborting now.");
+            exit(1);
+        }
+    }
+
     fclose(fp);
     stopLoading();
     return REDIS_OK;
index 60157ad8740f969af3327f4f7ef446fca7bb4d11..2be5d9cd11bf04888e6d28fa9674b801b1d1834f 100644 (file)
--- a/src/rdb.h
+++ b/src/rdb.h
@@ -9,7 +9,7 @@
 
 /* The current RDB version. When the format changes in a way that is no longer
  * backward compatible this number gets incremented. */
-#define REDIS_RDB_VERSION 4
+#define REDIS_RDB_VERSION 5
 
 /* Defines related to the dump file format. To store 32 bits lengths for short
  * keys requires a lot of space, so we check the most significant 2 bits of
index 84221addaaea1755881458a208fb4af388266e3b..f1fda57b5f568d6c96083b08b6182ed463cb21db 100644 (file)
@@ -318,14 +318,15 @@ void redisLogFromHandler(int level, const char *msg) {
         STDOUT_FILENO;
     if (fd == -1) return;
     ll2string(buf,sizeof(buf),getpid());
-    write(fd,"[",1);
-    write(fd,buf,strlen(buf));
-    write(fd," | signal handler] (",20);
+    if (write(fd,"[",1) == -1) goto err;
+    if (write(fd,buf,strlen(buf)) == -1) goto err;
+    if (write(fd," | signal handler] (",20) == -1) goto err;
     ll2string(buf,sizeof(buf),time(NULL));
-    write(fd,buf,strlen(buf));
-    write(fd,") ",2);
-    write(fd,msg,strlen(msg));
-    write(fd,"\n",1);
+    if (write(fd,buf,strlen(buf)) == -1) goto err;
+    if (write(fd,") ",2) == -1) goto err;
+    if (write(fd,msg,strlen(msg)) == -1) goto err;
+    if (write(fd,"\n",1) == -1) goto err;
+err:
     if (server.logfile) close(fd);
 }
 
@@ -1061,6 +1062,7 @@ void initServerConfig() {
     server.aof_filename = zstrdup("appendonly.aof");
     server.requirepass = NULL;
     server.rdb_compression = 1;
+    server.rdb_checksum = 1;
     server.activerehashing = 1;
     server.maxclients = REDIS_MAX_CLIENTS;
     server.bpop_blocked_clients = 0;
@@ -2040,7 +2042,7 @@ sds genRedisInfoString(char *section) {
         }
     }
 
-    /* Clusetr */
+    /* Cluster */
     if (allsections || defsections || !strcasecmp(section,"cluster")) {
         if (sections++) info = sdscat(info,"\r\n");
         info = sdscatprintf(info,
index ba209c7b994ad0f40b17ca8846b41c671a0f3543..42a9b5811b0d9ae85c0169677fb6308b90d200d4 100644 (file)
@@ -646,6 +646,7 @@ struct redisServer {
     int saveparamslen;              /* Number of saving points */
     char *rdb_filename;             /* Name of RDB file */
     int rdb_compression;            /* Use compression in RDB? */
+    int rdb_checksum;               /* Use RDB checksum? */
     time_t lastsave;                /* Unix time of last save succeeede */
     int lastbgsave_status;          /* REDIS_OK or REDIS_ERR */
     int stop_writes_on_bgsave_err;  /* Don't allow writes if can't BGSAVE */
@@ -827,7 +828,7 @@ extern dictType hashDictType;
 long long ustime(void);
 long long mstime(void);
 void getRandomHexChars(char *p, unsigned int len);
-uint64_t crc64(const unsigned char *s, uint64_t l);
+uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);
 void exitFromChild(int retcode);
 
 /* networking.c -- Networking and Client related operations */
index 95b1ee7e6042f9f97e28691ffc9d95cee2fb3df3..44165d71565fa68009e2cd0a23b63c63076be2df 100644 (file)
--- a/src/rio.c
+++ b/src/rio.c
@@ -1,9 +1,25 @@
+/* rio.c is a simple stream-oriented I/O abstraction that provides an interface
+ * to write code that can consume/produce data using different concrete input
+ * and output devices. For instance the same rdb.c code using the rio abstraction
+ * can be used to read and write the RDB format using in-memory buffers or files.
+ *
+ * A rio object provides the following methods:
+ *  read: read from stream.
+ *  write: write to stream.
+ *  tell: get the current offset.
+ *
+ * It is also possible to set a 'checksum' method that is used by rio.c in order
+ * to compute a checksum of the data written or read, or to query the rio object
+ * for the current checksum. */
+
 #include "fmacros.h"
 #include <string.h>
 #include <stdio.h>
 #include "rio.h"
 #include "util.h"
 
+uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l);
+
 /* Returns 1 or 0 for success/failure. */
 static size_t rioBufferWrite(rio *r, const void *buf, size_t len) {
     r->io.buffer.ptr = sdscatlen(r->io.buffer.ptr,(char*)buf,len);
@@ -44,6 +60,8 @@ static const rio rioBufferIO = {
     rioBufferRead,
     rioBufferWrite,
     rioBufferTell,
+    NULL,           /* update_checksum */
+    0,              /* current checksum */
     { { NULL, 0 } } /* union for io-specific vars */
 };
 
@@ -51,6 +69,8 @@ static const rio rioFileIO = {
     rioFileRead,
     rioFileWrite,
     rioFileTell,
+    NULL,           /* update_checksum */
+    0,              /* current checksum */
     { { NULL, 0 } } /* union for io-specific vars */
 };
 
@@ -65,6 +85,16 @@ void rioInitWithBuffer(rio *r, sds s) {
     r->io.buffer.pos = 0;
 }
 
+/* This function can be installed both in memory and file streams when checksum
+ * computation is needed. */
+void rioGenericUpdateChecksum(rio *r, const void *buf, size_t len) {
+    r->cksum = crc64(r->cksum,buf,len);
+}
+
+/* ------------------------------ Higher level interface ---------------------------
+ * The following higher level functions use lower level rio.c functions to help
+ * generating the Redis protocol for the Append Only File. */
+
 /* Write multi bulk count in the format: "*<count>\r\n". */
 size_t rioWriteBulkCount(rio *r, char prefix, int count) {
     char cbuf[128];
index 2a830eb575aacb751f5b24e29f4a5d1cafaddf09..8befe6676e78a3ff269073964eea050259d7fed5 100644 (file)
--- a/src/rio.h
+++ b/src/rio.h
@@ -2,6 +2,7 @@
 #define __REDIS_RIO_H
 
 #include <stdio.h>
+#include <stdint.h>
 #include "sds.h"
 
 struct _rio {
@@ -11,6 +12,14 @@ struct _rio {
     size_t (*read)(struct _rio *, void *buf, size_t len);
     size_t (*write)(struct _rio *, const void *buf, size_t len);
     off_t (*tell)(struct _rio *);
+    /* The update_cksum method if not NULL is used to compute the checksum of all the
+     * data that was read or written so far. The method should be designed so that
+     * can be called with the current checksum, and the buf and len fields pointing
+     * to the new block of data to add to the checksum computation. */
+    void (*update_cksum)(struct _rio *, const void *buf, size_t len);
+
+    /* The current checksum */
+    uint64_t cksum;
 
     /* Backend-specific vars. */
     union {
@@ -26,8 +35,26 @@ struct _rio {
 
 typedef struct _rio rio;
 
-#define rioWrite(rio,buf,len) ((rio)->write((rio),(buf),(len)))
-#define rioRead(rio,buf,len) ((rio)->read((rio),(buf),(len)))
+/* The following functions are our interface with the stream. They'll call the
+ * actual implementation of read / write / tell, and will update the checksum
+ * if needed. */
+
+static inline size_t rioWrite(rio *r, const void *buf, size_t len) {
+    if (r->update_cksum) r->update_cksum(r,buf,len);
+    return r->write(r,buf,len);
+}
+
+static inline size_t rioRead(rio *r, void *buf, size_t len) {
+    if (r->read(r,buf,len) == 1) {
+        if (r->update_cksum) r->update_cksum(r,buf,len);
+        return 1;
+    }
+    return 0;
+}
+
+static inline off_t rioTell(rio *r) {
+    return r->tell(r);
+}
 
 void rioInitWithFile(rio *r, FILE *fp);
 void rioInitWithBuffer(rio *r, sds s);
@@ -37,4 +64,6 @@ size_t rioWriteBulkString(rio *r, const char *buf, size_t len);
 size_t rioWriteBulkLongLong(rio *r, long long l);
 size_t rioWriteBulkDouble(rio *r, double d);
 
+void rioGenericUpdateChecksum(rio *r, const void *buf, size_t len);
+
 #endif
index 5e81636d659493389ee342e6751b75d89aacdd49..08f8649fc6fd75e804d379700a534708c439a6d0 100644 (file)
@@ -1 +1 @@
-#define REDIS_VERSION "2.9.6"
+#define REDIS_VERSION "2.9.7"
index 2ec3aad1c16c4bf7679af16fe45bbbdf4331ee12..598a392916538a1900cb711dd3ec31668444bb64 100644 (file)
@@ -38,6 +38,7 @@ set ::all_tests {
     unit/scripting
     unit/maxmemory
     unit/introspection
+    unit/limits
     unit/obuf-limits
     unit/dump
 }
diff --git a/tests/unit/limits.tcl b/tests/unit/limits.tcl
new file mode 100644 (file)
index 0000000..9988983
--- /dev/null
@@ -0,0 +1,13 @@
+start_server {tags {"limits"} overrides {maxclients 10}} {
+    test {Check if maxclients works refusing connections} {
+        set c 0
+        catch {
+            while 1 {
+                incr c
+                redis_deferring_client
+            }
+        } e
+        assert {$c > 8 && $c <= 10}
+        set e
+    } {*ERR max*reached*}
+}