diff -Nru redis-2.6.12/.gitignore redis-2.6.13/.gitignore --- redis-2.6.12/.gitignore 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/.gitignore 2013-04-30 13:15:56.000000000 +0000 @@ -1,8 +1,13 @@ .*.swp *.o -*.rdb *.log -redis-* +dump.rdb +redis-benchmark +redis-check-aof +redis-check-dump +redis-cli +redis-sentinel +redis-server doc-tools release misc/* diff -Nru redis-2.6.12/00-RELEASENOTES redis-2.6.13/00-RELEASENOTES --- redis-2.6.12/00-RELEASENOTES 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/00-RELEASENOTES 2013-04-30 13:15:56.000000000 +0000 @@ -14,6 +14,29 @@ CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP. -------------------------------------------------------------------------------- +--[ Redis 2.6.13 ] + +UPGRADE URGENCY: MODERATE, nothing very critical but upgrading is suggested + if you experienced: + + 1) Strange issues with Lua scripting. + 2) Not reconfigured reappearing master using Sentinel. + 3) Server continusly trying to save on save error. + + This version of Redis may also help with AOF and slow / busy + disks and latency issues. + +* [FIX] Throttle BGSAVE attempt on saving error. +* [FIX] redis-cli: raise error on bad command line switch. +* [FIX] Redis/Jemalloc Gitignore were too aggressive. +* [FIX] Test: fix RDB test checking file permissions. +* [FIX] Sentinel: always redirect on master->slave transition. +* [FIX] Lua updated to version 5.1.5. Fixes rare scripting issues. +* [NEW] AOF: improved latency figures with slow/busy disks. +* [NEW] Sentinel: turn old master into a slave when it comes back. +* [NEW] More explicit panic message on out of memory. +* [NEW] redis-cli: --latency-history mode implemented. + --[ Redis 2.6.12 ] UPGRADE URGENCY: MODERATE, nothing very critical but a few non trivial bugs. diff -Nru redis-2.6.12/debian/changelog redis-2.6.13/debian/changelog --- redis-2.6.12/debian/changelog 2013-04-01 18:29:48.000000000 +0000 +++ redis-2.6.13/debian/changelog 2013-05-01 00:03:04.000000000 +0000 @@ -1,3 +1,9 @@ +redis (2:2.6.13-1chl1~lucid1) lucid; urgency=low + + * Package 2.6.13 for lucid. + + -- Chris Lea Tue, 30 Apr 2013 17:02:40 -0700 + redis (2:2.6.12-1chl1~lucid1) lucid; urgency=low * Package 2.6.12 for lucid. diff -Nru redis-2.6.12/deps/jemalloc/.gitignore redis-2.6.13/deps/jemalloc/.gitignore --- redis-2.6.12/deps/jemalloc/.gitignore 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/jemalloc/.gitignore 2013-04-30 13:15:56.000000000 +0000 @@ -2,24 +2,19 @@ /config.stamp /config.log /config.status -/configure /doc/html.xsl /doc/manpages.xsl /doc/jemalloc.xml -/doc/jemalloc.html -/doc/jemalloc.3 /lib/ /Makefile /include/jemalloc/internal/jemalloc_internal\.h /include/jemalloc/internal/size_classes\.h /include/jemalloc/jemalloc\.h /include/jemalloc/jemalloc_defs\.h -/test/jemalloc_test\.h /src/*.[od] /test/*.[od] /test/*.out /test/[a-zA-Z_]* !test/*.c !test/*.exp -/VERSION /bin/jemalloc.sh diff -Nru redis-2.6.12/deps/lua/COPYRIGHT redis-2.6.13/deps/lua/COPYRIGHT --- redis-2.6.12/deps/lua/COPYRIGHT 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/COPYRIGHT 2013-04-30 13:15:56.000000000 +0000 @@ -9,7 +9,7 @@ =============================================================================== -Copyright (C) 1994-2008 Lua.org, PUC-Rio. +Copyright (C) 1994-2012 Lua.org, PUC-Rio. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff -Nru redis-2.6.12/deps/lua/Makefile redis-2.6.13/deps/lua/Makefile --- redis-2.6.12/deps/lua/Makefile 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/Makefile 2013-04-30 13:15:56.000000000 +0000 @@ -48,7 +48,7 @@ # Lua version and release. V= 5.1 -R= 5.1.4 +R= 5.1.5 all: $(PLAT) Binary files /tmp/YPrt9D2Tmo/redis-2.6.12/deps/lua/doc/amazon.gif and /tmp/iSpxnEiGIl/redis-2.6.13/deps/lua/doc/amazon.gif differ diff -Nru redis-2.6.12/deps/lua/doc/contents.html redis-2.6.13/deps/lua/doc/contents.html --- redis-2.6.12/deps/lua/doc/contents.html 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/doc/contents.html 2013-04-30 13:15:56.000000000 +0000 @@ -3,11 +3,10 @@ Lua 5.1 Reference Manual - contents - + @@ -20,7 +19,13 @@ Lua 5.1 Reference Manual -This is an online version of +

+The reference manual is the official definition of the Lua language. +For a complete introduction to Lua programming, see the book +Programming in Lua. + +

+This manual is also available as a book:

@@ -29,128 +34,119 @@
by R. Ierusalimschy, L. H. de Figueiredo, W. Celes
Lua.org, August 2006
ISBN 85-903798-3-3 -
-[Buy from Amazon]
-

-Buy a copy of this book and +

+Buy a copy +of this book and help to support the Lua project. -

-The reference manual is the official definition of the Lua language. -For a complete introduction to Lua programming, see the book -Programming in Lua.

- start · contents · index · -português -· -español +other versions


-Copyright © 2006-2008 Lua.org, PUC-Rio. +Copyright © 2006–2012 Lua.org, PUC-Rio. Freely available under the terms of the -Lua license. +Lua license. -

Contents

-

  • 3 - The Application Program Interface +
  • 3 – The Application Program Interface

    -

  • 4 - The Auxiliary Library +
  • 4 – The Auxiliary Library

    -

  • 5 - Standard Libraries +
  • 5 – Standard Libraries

    -

  • 6 - Lua Stand-alone +
  • 6 – Lua Stand-alone

    -

  • 7 - Incompatibilities with the Previous Version +
  • 7 – Incompatibilities with the Previous Version

    -

  • 8 - The Complete Syntax of Lua +
  • 8 – The Complete Syntax of Lua

    Index

    @@ -160,6 +156,8 @@

    Lua functions

    _G
    _VERSION
    +

    + assert
    collectgarbage
    dofile
    @@ -487,12 +485,12 @@


    - + Last update: -Sat Jan 19 13:24:29 BRST 2008 +Mon Feb 13 18:53:32 BRST 2012 diff -Nru redis-2.6.12/deps/lua/doc/lua.css redis-2.6.13/deps/lua/doc/lua.css --- redis-2.6.12/deps/lua/doc/lua.css 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/doc/lua.css 2013-04-30 13:15:56.000000000 +0000 @@ -1,17 +1,37 @@ body { color: #000000 ; background-color: #FFFFFF ; - font-family: sans-serif ; + font-family: Helvetica, Arial, sans-serif ; text-align: justify ; - margin-right: 20px ; - margin-left: 20px ; + margin-right: 30px ; + margin-left: 30px ; } h1, h2, h3, h4 { + font-family: Verdana, Geneva, sans-serif ; font-weight: normal ; font-style: italic ; } +h2 { + padding-top: 0.4em ; + padding-bottom: 0.4em ; + padding-left: 30px ; + padding-right: 30px ; + margin-left: -30px ; + background-color: #E0E0FF ; +} + +h3 { + padding-left: 0.5em ; + border-left: solid #E0E0FF 1em ; +} + +table h3 { + padding-left: 0px ; + border-left: none ; +} + a:link { color: #000080 ; background-color: inherit ; @@ -39,3 +59,25 @@ background-color: #a0a0a0 ; } +:target { + background-color: #F8F8F8 ; + padding: 8px ; + border: solid #a0a0a0 2px ; +} + +.footer { + color: gray ; + font-size: small ; +} + +input[type=text] { + border: solid #a0a0a0 2px ; + border-radius: 2em ; + -moz-border-radius: 2em ; + background-image: url('images/search.png') ; + background-repeat: no-repeat; + background-position: 4px center ; + padding-left: 20px ; + height: 2em ; +} + diff -Nru redis-2.6.12/deps/lua/doc/manual.css redis-2.6.13/deps/lua/doc/manual.css --- redis-2.6.12/deps/lua/doc/manual.css 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/doc/manual.css 2013-04-30 13:15:56.000000000 +0000 @@ -1,13 +1,24 @@ h3 code { font-family: inherit ; + font-size: inherit ; } -pre { - font-size: 105% ; +pre, code { + font-size: 12pt ; } span.apii { float: right ; font-family: inherit ; + font-style: normal ; + font-size: small ; + color: gray ; } +p+h1, ul+h1 { + padding-top: 0.4em ; + padding-bottom: 0.4em ; + padding-left: 30px ; + margin-left: -30px ; + background-color: #E0E0FF ; +} diff -Nru redis-2.6.12/deps/lua/doc/manual.html redis-2.6.13/deps/lua/doc/manual.html --- redis-2.6.12/deps/lua/doc/manual.html 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/doc/manual.html 2013-04-30 13:15:56.000000000 +0000 @@ -19,9 +19,9 @@ by Roberto Ierusalimschy, Luiz Henrique de Figueiredo, Waldemar Celes

    -Copyright © 2006-2008 Lua.org, PUC-Rio. +Copyright © 2006–2012 Lua.org, PUC-Rio. Freely available under the terms of the -Lua license. +Lua license.


    @@ -29,11 +29,13 @@ contents · index +· +other versions

    - + @@ -5645,7 +5647,7 @@

      -
    • basic library,
    • which includes the coroutine sub-library; +
    • basic library, which includes the coroutine sub-library;
    • package library;
    • @@ -5709,7 +5711,7 @@

      -


      collectgarbage (opt [, arg])

      +

      collectgarbage ([opt [, arg]])

      @@ -5718,6 +5720,11 @@

        +
      • "collect": +performs a full garbage-collection cycle. +This is the default option. +
      • +
      • "stop": stops the garbage collector.
      • @@ -5726,10 +5733,6 @@ restarts the garbage collector. -
      • "collect": -performs a full garbage-collection cycle. -
      • -
      • "count": returns the total memory in use by Lua (in Kbytes).
      • @@ -5760,7 +5763,7 @@

        -


        dofile (filename)

        +

        dofile ([filename])

        Opens the named file and executes its contents as a Lua chunk. When called without arguments, dofile executes the contents of the standard input (stdin). @@ -8421,7 +8424,7 @@

        -


        debug.traceback ([thread,] [message] [, level])

        +

        debug.traceback ([thread,] [message [, level]])

        @@ -8789,12 +8792,12 @@


        - + Last update: -Mon Aug 18 13:25:46 BRT 2008 +Mon Feb 13 18:54:19 BRST 2012 diff -Nru redis-2.6.12/deps/lua/doc/readme.html redis-2.6.13/deps/lua/doc/readme.html --- redis-2.6.12/deps/lua/doc/readme.html 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/doc/readme.html 2013-04-30 13:15:56.000000000 +0000 @@ -12,7 +12,7 @@ Documentation -This is the documentation included in the source distribution of Lua 5.1.4. +This is the documentation included in the source distribution of Lua 5.1.5.
        • Reference manual @@ -33,7 +33,7 @@
          Last update: -Tue Aug 12 14:46:07 BRT 2008 +Fri Feb 3 09:44:42 BRST 2012 diff -Nru redis-2.6.12/deps/lua/etc/lua.pc redis-2.6.13/deps/lua/etc/lua.pc --- redis-2.6.12/deps/lua/etc/lua.pc 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/etc/lua.pc 2013-04-30 13:15:56.000000000 +0000 @@ -5,7 +5,7 @@ # grep '^V=' ../Makefile V= 5.1 # grep '^R=' ../Makefile -R= 5.1.4 +R= 5.1.5 # grep '^INSTALL_.*=' ../Makefile | sed 's/INSTALL_TOP/prefix/' prefix= /usr/local diff -Nru redis-2.6.12/deps/lua/src/Makefile redis-2.6.13/deps/lua/src/Makefile --- redis-2.6.12/deps/lua/src/Makefile 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/Makefile 2013-04-30 13:15:56.000000000 +0000 @@ -48,7 +48,7 @@ a: $(ALL_A) $(LUA_A): $(CORE_O) $(LIB_O) - $(AR) $@ $? + $(AR) $@ $(CORE_O) $(LIB_O) # DLL needs all object files $(RANLIB) $@ $(LUA_T): $(LUA_O) $(LUA_A) diff -Nru redis-2.6.12/deps/lua/src/lbaselib.c redis-2.6.13/deps/lua/src/lbaselib.c --- redis-2.6.12/deps/lua/src/lbaselib.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/lbaselib.c 2013-04-30 13:15:56.000000000 +0000 @@ -631,7 +631,7 @@ luaL_register(L, "_G", base_funcs); lua_pushliteral(L, LUA_VERSION); lua_setglobal(L, "_VERSION"); /* set global _VERSION */ - /* `ipairs' and `pairs' need auxliliary functions as upvalues */ + /* `ipairs' and `pairs' need auxiliary functions as upvalues */ auxopen(L, "ipairs", luaB_ipairs, ipairsaux); auxopen(L, "pairs", luaB_pairs, luaB_next); /* `newproxy' needs a weaktable as upvalue */ diff -Nru redis-2.6.12/deps/lua/src/lcode.c redis-2.6.13/deps/lua/src/lcode.c --- redis-2.6.12/deps/lua/src/lcode.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/lcode.c 2013-04-30 13:15:56.000000000 +0000 @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ +** $Id: lcode.c,v 2.25.1.5 2011/01/31 14:53:16 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -544,10 +544,6 @@ pc = NO_JUMP; /* always true; do nothing */ break; } - case VFALSE: { - pc = luaK_jump(fs); /* always jump */ - break; - } case VJMP: { invertjump(fs, e); pc = e->u.s.info; @@ -572,10 +568,6 @@ pc = NO_JUMP; /* always false; do nothing */ break; } - case VTRUE: { - pc = luaK_jump(fs); /* always jump */ - break; - } case VJMP: { pc = e->u.s.info; break; diff -Nru redis-2.6.12/deps/lua/src/ldblib.c redis-2.6.13/deps/lua/src/ldblib.c --- redis-2.6.12/deps/lua/src/ldblib.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/ldblib.c 2013-04-30 13:15:56.000000000 +0000 @@ -1,5 +1,5 @@ /* -** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $ +** $Id: ldblib.c,v 1.104.1.4 2009/08/04 18:50:18 roberto Exp $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ @@ -45,6 +45,7 @@ static int db_getfenv (lua_State *L) { + luaL_checkany(L, 1); lua_getfenv(L, 1); return 1; } diff -Nru redis-2.6.12/deps/lua/src/ldo.c redis-2.6.13/deps/lua/src/ldo.c --- redis-2.6.12/deps/lua/src/ldo.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/ldo.c 2013-04-30 13:15:56.000000000 +0000 @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ +** $Id: ldo.c,v 2.38.1.4 2012/01/18 02:27:10 roberto Exp $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -217,6 +217,7 @@ int nvar = actual - nfixargs; /* number of extra arguments */ lua_assert(p->is_vararg & VARARG_HASARG); luaC_checkGC(L); + luaD_checkstack(L, p->maxstacksize); htab = luaH_new(L, nvar, 1); /* create `arg' table */ for (i=0; itop - nvar + i); diff -Nru redis-2.6.12/deps/lua/src/lgc.c redis-2.6.13/deps/lua/src/lgc.c --- redis-2.6.12/deps/lua/src/lgc.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/lgc.c 2013-04-30 13:15:56.000000000 +0000 @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: lgc.c,v 2.38.1.2 2011/03/18 18:05:38 roberto Exp $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -627,7 +627,6 @@ } } else { - lua_assert(g->totalbytes >= g->estimate); setthreshold(g); } } diff -Nru redis-2.6.12/deps/lua/src/liolib.c redis-2.6.13/deps/lua/src/liolib.c --- redis-2.6.12/deps/lua/src/liolib.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/liolib.c 2013-04-30 13:15:56.000000000 +0000 @@ -1,5 +1,5 @@ /* -** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ +** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $ ** Standard I/O (and system) library ** See Copyright Notice in lua.h */ @@ -276,7 +276,10 @@ lua_pushnumber(L, d); return 1; } - else return 0; /* read fails */ + else { + lua_pushnil(L); /* "result" to be removed */ + return 0; /* read fails */ + } } diff -Nru redis-2.6.12/deps/lua/src/llex.c redis-2.6.13/deps/lua/src/llex.c --- redis-2.6.12/deps/lua/src/llex.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/llex.c 2013-04-30 13:15:56.000000000 +0000 @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ +** $Id: llex.c,v 2.20.1.2 2009/11/23 14:58:22 roberto Exp $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -118,8 +118,10 @@ lua_State *L = ls->L; TString *ts = luaS_newlstr(L, str, l); TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ - if (ttisnil(o)) + if (ttisnil(o)) { setbvalue(o, 1); /* make sure `str' will not be collected */ + luaC_checkGC(L); + } return ts; } diff -Nru redis-2.6.12/deps/lua/src/loadlib.c redis-2.6.13/deps/lua/src/loadlib.c --- redis-2.6.12/deps/lua/src/loadlib.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/loadlib.c 2013-04-30 13:15:56.000000000 +0000 @@ -1,5 +1,5 @@ /* -** $Id: loadlib.c,v 1.52.1.3 2008/08/06 13:29:28 roberto Exp $ +** $Id: loadlib.c,v 1.52.1.4 2009/09/09 13:17:16 roberto Exp $ ** Dynamic library loader for Lua ** See Copyright Notice in lua.h ** @@ -639,7 +639,7 @@ lua_pushvalue(L, -1); lua_replace(L, LUA_ENVIRONINDEX); /* create `loaders' table */ - lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1); + lua_createtable(L, sizeof(loaders)/sizeof(loaders[0]) - 1, 0); /* fill it with pre-defined loaders */ for (i=0; loaders[i] != NULL; i++) { lua_pushcfunction(L, loaders[i]); diff -Nru redis-2.6.12/deps/lua/src/lparser.c redis-2.6.13/deps/lua/src/lparser.c --- redis-2.6.12/deps/lua/src/lparser.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/lparser.c 2013-04-30 13:15:56.000000000 +0000 @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ +** $Id: lparser.c,v 2.42.1.4 2011/10/21 19:31:42 roberto Exp $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -374,9 +374,9 @@ lua_assert(luaG_checkcode(f)); lua_assert(fs->bl == NULL); ls->fs = fs->prev; - L->top -= 2; /* remove table and prototype from the stack */ /* last token read was anchored in defunct function; must reanchor it */ if (fs) anchor_token(ls); + L->top -= 2; /* remove table and prototype from the stack */ } diff -Nru redis-2.6.12/deps/lua/src/lstrlib.c redis-2.6.13/deps/lua/src/lstrlib.c --- redis-2.6.12/deps/lua/src/lstrlib.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/lstrlib.c 2013-04-30 13:15:56.000000000 +0000 @@ -1,5 +1,5 @@ /* -** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ +** $Id: lstrlib.c,v 1.132.1.5 2010/05/14 15:34:19 roberto Exp $ ** Standard library for string operations and pattern-matching ** See Copyright Notice in lua.h */ @@ -754,6 +754,7 @@ static int str_format (lua_State *L) { + int top = lua_gettop(L); int arg = 1; size_t sfl; const char *strfrmt = luaL_checklstring(L, arg, &sfl); @@ -768,7 +769,8 @@ else { /* format item */ char form[MAX_FORMAT]; /* to store the format (`%...') */ char buff[MAX_ITEM]; /* to store the formatted item */ - arg++; + if (++arg > top) + luaL_argerror(L, arg, "no value"); strfrmt = scanformat(L, strfrmt, form); switch (*strfrmt++) { case 'c': { diff -Nru redis-2.6.12/deps/lua/src/lua.h redis-2.6.13/deps/lua/src/lua.h --- redis-2.6.12/deps/lua/src/lua.h 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/lua.h 2013-04-30 13:15:56.000000000 +0000 @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ +** $Id: lua.h,v 1.218.1.7 2012/01/13 20:36:20 roberto Exp $ ** Lua - An Extensible Extension Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -17,9 +17,9 @@ #define LUA_VERSION "Lua 5.1" -#define LUA_RELEASE "Lua 5.1.4" +#define LUA_RELEASE "Lua 5.1.5" #define LUA_VERSION_NUM 501 -#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" +#define LUA_COPYRIGHT "Copyright (C) 1994-2012 Lua.org, PUC-Rio" #define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" @@ -362,7 +362,7 @@ /****************************************************************************** -* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. +* Copyright (C) 1994-2012 Lua.org, PUC-Rio. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the diff -Nru redis-2.6.12/deps/lua/src/lvm.c redis-2.6.13/deps/lua/src/lvm.c --- redis-2.6.12/deps/lua/src/lvm.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/deps/lua/src/lvm.c 2013-04-30 13:15:56.000000000 +0000 @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ +** $Id: lvm.c,v 2.63.1.5 2011/08/17 20:43:11 roberto Exp $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -133,6 +133,7 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { int loop; + TValue temp; for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; if (ttistable(t)) { /* `t' is a table? */ @@ -141,6 +142,7 @@ if (!ttisnil(oldval) || /* result is no nil? */ (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ setobj2t(L, oldval, val); + h->flags = 0; luaC_barriert(L, h, val); return; } @@ -152,7 +154,9 @@ callTM(L, tm, t, key, val); return; } - t = tm; /* else repeat with `tm' */ + /* else repeat with `tm' */ + setobj(L, &temp, tm); /* avoid pointing inside table (may rehash) */ + t = &temp; } luaG_runerror(L, "loop in settable"); } diff -Nru redis-2.6.12/redis.conf redis-2.6.13/redis.conf --- redis-2.6.12/redis.conf 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/redis.conf 2013-04-30 13:15:56.000000000 +0000 @@ -580,6 +580,12 @@ # 100 only in environments where very low latency is required. hz 10 +# When a child rewrites the AOF file, if the following option is enabled +# the file will be fsync-ed every 32 MB of data generated. This is useful +# in order to commit the file to the disk more incrementally and avoid +# big latency spikes. +aof-rewrite-incremental-fsync yes + ################################## INCLUDES ################################### # Include one or more other config files here. This is useful if you diff -Nru redis-2.6.12/src/aof.c redis-2.6.13/src/aof.c --- redis-2.6.12/src/aof.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/src/aof.c 2013-04-30 13:15:56.000000000 +0000 @@ -855,6 +855,8 @@ } rioInitWithFile(&aof,fp); + if (server.aof_rewrite_incremental_fsync) + rioSetAutoSync(&aof,REDIS_AOF_AUTOSYNC_BYTES); for (j = 0; j < server.dbnum; j++) { char selectcmd[] = "*2\r\n$6\r\nSELECT\r\n"; redisDb *db = server.db+j; diff -Nru redis-2.6.12/src/config.c redis-2.6.13/src/config.c --- redis-2.6.12/src/config.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/src/config.c 2013-04-30 13:15:56.000000000 +0000 @@ -317,6 +317,12 @@ argc == 2) { server.aof_rewrite_min_size = memtoll(argv[1],NULL); + } else if (!strcasecmp(argv[0],"aof-rewrite-incremental-fsync") && + argc == 2) + { + if ((server.aof_rewrite_incremental_fsync = yesnotoi(argv[1])) == -1) { + err = "argument must be 'yes' or 'no'"; goto loaderr; + } } else if (!strcasecmp(argv[0],"requirepass") && argc == 2) { if (strlen(argv[1]) > REDIS_AUTHPASS_MAX_LEN) { err = "Password is longer than REDIS_AUTHPASS_MAX_LEN"; @@ -566,6 +572,11 @@ } else if (!strcasecmp(c->argv[2]->ptr,"auto-aof-rewrite-min-size")) { if (getLongLongFromObject(o,&ll) == REDIS_ERR || ll < 0) goto badfmt; server.aof_rewrite_min_size = ll; + } else if (!strcasecmp(c->argv[2]->ptr,"aof-rewrite-incremental-fsync")) { + int yn = yesnotoi(o->ptr); + + if (yn == -1) goto badfmt; + server.aof_rewrite_incremental_fsync = yn; } else if (!strcasecmp(c->argv[2]->ptr,"save")) { int vlen, j; sds *v = sdssplitlen(o->ptr,sdslen(o->ptr)," ",1,&vlen); @@ -847,6 +858,8 @@ config_get_bool_field("activerehashing", server.activerehashing); config_get_bool_field("repl-disable-tcp-nodelay", server.repl_disable_tcp_nodelay); + config_get_bool_field("aof-rewrite-incremental-fsync", + server.aof_rewrite_incremental_fsync); /* Everything we can't handle with macros follows. */ diff -Nru redis-2.6.12/src/rdb.c redis-2.6.13/src/rdb.c --- redis-2.6.12/src/rdb.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/src/rdb.c 2013-04-30 13:15:56.000000000 +0000 @@ -722,6 +722,7 @@ if (server.rdb_child_pid != -1) return REDIS_ERR; server.dirty_before_bgsave = server.dirty; + server.lastbgsave_try = time(NULL); start = ustime(); if ((childpid = fork()) == 0) { diff -Nru redis-2.6.12/src/redis-cli.c redis-2.6.13/src/redis-cli.c --- redis-2.6.12/src/redis-cli.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/src/redis-cli.c 2013-04-30 13:15:56.000000000 +0000 @@ -72,6 +72,7 @@ int monitor_mode; int pubsub_mode; int latency_mode; + int latency_history; int cluster_mode; int cluster_reissue_command; int slave_mode; @@ -700,6 +701,9 @@ config.output = OUTPUT_CSV; } else if (!strcmp(argv[i],"--latency")) { config.latency_mode = 1; + } else if (!strcmp(argv[i],"--latency-history")) { + config.latency_mode = 1; + config.latency_history = 1; } else if (!strcmp(argv[i],"--slave")) { config.slave_mode = 1; } else if (!strcmp(argv[i],"--stat")) { @@ -724,7 +728,15 @@ sdsfree(version); exit(0); } else { - break; + if (argv[i][0] == '-') { + fprintf(stderr, + "Unrecognized option or bad number of args for: '%s'\n", + argv[i]); + exit(1); + } else { + /* Likely the command name, stop here. */ + break; + } } } return i; @@ -753,26 +765,29 @@ "redis-cli %s\n" "\n" "Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]\n" -" -h Server hostname (default: 127.0.0.1)\n" -" -p Server port (default: 6379)\n" -" -s Server socket (overrides hostname and port)\n" -" -a Password to use when connecting to the server\n" -" -r Execute specified command N times\n" -" -i When -r is used, waits seconds per command.\n" -" It is possible to specify sub-second times like -i 0.1\n" -" -n Database number\n" -" -x Read last argument from STDIN\n" -" -d Multi-bulk delimiter in for raw formatting (default: \\n)\n" -" -c Enable cluster mode (follow -ASK and -MOVED redirections)\n" -" --raw Use raw formatting for replies (default when STDOUT is not a tty)\n" -" --latency Enter a special mode continuously sampling latency\n" -" --slave Simulate a slave showing commands received from the master\n" -" --rdb Transfer an RDB dump from remote server to local file.\n" -" --pipe Transfer raw Redis protocol from stdin to server\n" -" --bigkeys Sample Redis keys looking for big keys\n" -" --eval Send an EVAL command using the Lua script at \n" -" --help Output this help and exit\n" -" --version Output version and exit\n" +" -h Server hostname (default: 127.0.0.1)\n" +" -p Server port (default: 6379)\n" +" -s Server socket (overrides hostname and port)\n" +" -a Password to use when connecting to the server\n" +" -r Execute specified command N times\n" +" -i When -r is used, waits seconds per command.\n" +" It is possible to specify sub-second times like -i 0.1\n" +" -n Database number\n" +" -x Read last argument from STDIN\n" +" -d Multi-bulk delimiter in for raw formatting (default: \\n)\n" +" -c Enable cluster mode (follow -ASK and -MOVED redirections)\n" +" --raw Use raw formatting for replies (default when STDOUT is\n" +" not a tty)\n" +" --latency Enter a special mode continuously sampling latency\n" +" --latency-history Like --latency but tracking latency changes over time.\n" +" Default time interval is 15 sec. Change it using -i.\n" +" --slave Simulate a slave showing commands received from the master\n" +" --rdb Transfer an RDB dump from remote server to local file.\n" +" --pipe Transfer raw Redis protocol from stdin to server\n" +" --bigkeys Sample Redis keys looking for big keys\n" +" --eval Send an EVAL command using the Lua script at \n" +" --help Output this help and exit\n" +" --version Output version and exit\n" "\n" "Examples:\n" " cat /etc/passwd | redis-cli -x set mypasswd\n" @@ -943,10 +958,16 @@ return cliSendCommand(argc+3-got_comma, argv2, config.repeat); } +#define LATENCY_SAMPLE_RATE 10 /* milliseconds. */ +#define LATENCY_HISTORY_DEFAULT_INTERVAL 15000 /* milliseconds. */ static void latencyMode(void) { redisReply *reply; long long start, latency, min = 0, max = 0, tot = 0, count = 0; + long long history_interval = + config.interval ? config.interval/1000 : + LATENCY_HISTORY_DEFAULT_INTERVAL; double avg; + long long history_start = mstime(); if (!context) exit(1); while(1) { @@ -971,7 +992,13 @@ printf("\x1b[0G\x1b[2Kmin: %lld, max: %lld, avg: %.2f (%lld samples)", min, max, avg, count); fflush(stdout); - usleep(10000); + if (config.latency_history && mstime()-history_start > history_interval) + { + printf(" -- %.2f seconds range\n", (float)(mstime()-history_start)/1000); + history_start = mstime(); + min = max = tot = count = 0; + } + usleep(LATENCY_SAMPLE_RATE * 1000); } } @@ -1452,6 +1479,7 @@ config.monitor_mode = 0; config.pubsub_mode = 0; config.latency_mode = 0; + config.latency_history = 0; config.cluster_mode = 0; config.slave_mode = 0; config.getrdb_mode = 0; diff -Nru redis-2.6.12/src/redis.c redis-2.6.13/src/redis.c --- redis-2.6.12/src/redis.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/src/redis.c 2013-04-30 13:15:56.000000000 +0000 @@ -995,8 +995,16 @@ for (j = 0; j < server.saveparamslen; j++) { struct saveparam *sp = server.saveparams+j; + /* Save if we reached the given amount of changes, + * the given amount of seconds, and if the latest bgsave was + * successful or if, in case of an error, at least + * REDIS_BGSAVE_RETRY_DELAY seconds already elapsed. */ if (server.dirty >= sp->changes && - server.unixtime-server.lastsave > sp->seconds) { + server.unixtime-server.lastsave > sp->seconds && + (server.unixtime-server.lastbgsave_try > + REDIS_BGSAVE_RETRY_DELAY || + server.lastbgsave_status == REDIS_OK)) + { redisLog(REDIS_NOTICE,"%d changes in %d seconds. Saving...", sp->changes, sp->seconds); rdbSaveBackground(server.rdb_filename); @@ -1181,6 +1189,7 @@ server.aof_fd = -1; server.aof_selected_db = -1; /* Make sure the first time will not match */ server.aof_flush_postponed_start = 0; + server.aof_rewrite_incremental_fsync = 1; server.pidfile = zstrdup("/var/run/redis.pid"); server.rdb_filename = zstrdup("dump.rdb"); server.aof_filename = zstrdup("appendonly.aof"); @@ -1375,7 +1384,8 @@ server.aof_child_pid = -1; aofRewriteBufferReset(); server.aof_buf = sdsempty(); - server.lastsave = time(NULL); + server.lastsave = time(NULL); /* At startup we consider the DB saved. */ + server.lastbgsave_try = 0; /* At startup we never tried to BGSAVE. */ server.rdb_save_time_last = -1; server.rdb_save_time_start = -1; server.dirty = 0; @@ -2614,7 +2624,7 @@ void redisOutOfMemoryHandler(size_t allocation_size) { redisLog(REDIS_WARNING,"Out Of Memory allocating %zu bytes!", allocation_size); - redisPanic("OOM"); + redisPanic("Redis aborting for OUT OF MEMORY"); } int main(int argc, char **argv) { diff -Nru redis-2.6.12/src/redis.h redis-2.6.13/src/redis.h --- redis-2.6.12/src/redis.h 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/src/redis.h 2013-04-30 13:15:56.000000000 +0000 @@ -94,6 +94,7 @@ #define REDIS_REPL_PING_SLAVE_PERIOD 10 #define REDIS_RUN_ID_SIZE 40 #define REDIS_OPS_SEC_SAMPLES 16 +#define REDIS_BGSAVE_RETRY_DELAY 5 /* Wait a few secs before trying again. */ /* Protocol and I/O related defines */ #define REDIS_MAX_QUERYBUF_LEN (1024*1024*1024) /* 1GB max query buffer. */ @@ -101,6 +102,7 @@ #define REDIS_REPLY_CHUNK_BYTES (16*1024) /* 16k output buffer */ #define REDIS_INLINE_MAX_SIZE (1024*64) /* Max size of inline reads */ #define REDIS_MBULK_BIG_ARG (1024*32) +#define REDIS_AOF_AUTOSYNC_BYTES (1024*1024*32) /* fdatasync every 32MB */ /* Hash table parameters */ #define REDIS_HT_MINFILL 10 /* Minimal hash table fill 10% */ @@ -583,6 +585,7 @@ time_t aof_rewrite_time_start; /* Current AOF rewrite start time. */ int aof_lastbgrewrite_status; /* REDIS_OK or REDIS_ERR */ unsigned long aof_delayed_fsync; /* delayed AOF fsync() counter */ + int aof_rewrite_incremental_fsync;/* fsync incrementally while rewriting? */ /* RDB persistence */ long long dirty; /* Changes to DB from the last save */ long long dirty_before_bgsave; /* Used to restore dirty on failed BGSAVE */ @@ -593,6 +596,7 @@ int rdb_compression; /* Use compression in RDB? */ int rdb_checksum; /* Use RDB checksum? */ time_t lastsave; /* Unix time of last successful save */ + time_t lastbgsave_try; /* Unix time of last attempted bgsave */ time_t rdb_save_time_last; /* Time used by last RDB save run. */ time_t rdb_save_time_start; /* Current RDB save start time. */ int lastbgsave_status; /* REDIS_OK or REDIS_ERR */ diff -Nru redis-2.6.12/src/rio.c redis-2.6.13/src/rio.c --- redis-2.6.12/src/rio.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/src/rio.c 2013-04-30 13:15:56.000000000 +0000 @@ -48,8 +48,11 @@ #include "fmacros.h" #include #include +#include #include "rio.h" #include "util.h" +#include "config.h" +#include "redis.h" uint64_t crc64(uint64_t crc, const unsigned char *s, uint64_t l); @@ -76,7 +79,18 @@ /* Returns 1 or 0 for success/failure. */ static size_t rioFileWrite(rio *r, const void *buf, size_t len) { - return fwrite(buf,len,1,r->io.file.fp); + size_t retval; + + retval = fwrite(buf,len,1,r->io.file.fp); + r->io.file.buffered += len; + + if (r->io.file.autosync && + r->io.file.buffered >= r->io.file.autosync) + { + aof_fsync(fileno(r->io.file.fp)); + r->io.file.buffered = 0; + } + return retval; } /* Returns 1 or 0 for success/failure. */ @@ -110,6 +124,8 @@ void rioInitWithFile(rio *r, FILE *fp) { *r = rioFileIO; r->io.file.fp = fp; + r->io.file.buffered = 0; + r->io.file.autosync = 0; } void rioInitWithBuffer(rio *r, sds s) { @@ -124,6 +140,19 @@ r->cksum = crc64(r->cksum,buf,len); } +/* Set the file-based rio object to auto-fsync every 'bytes' file written. + * By default this is set to zero that means no automatic file sync is + * performed. + * + * This feature is useful in a few contexts since when we rely on OS write + * buffers sometimes the OS buffers way too much, resulting in too many + * disk I/O concentrated in very little time. When we fsync in an explicit + * way instead the I/O pressure is more distributed across time. */ +void rioSetAutoSync(rio *r, off_t bytes) { + redisAssert(r->read == rioFileIO.read); + r->io.file.autosync = bytes; +} + /* ------------------------------ 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. */ diff -Nru redis-2.6.12/src/rio.h redis-2.6.13/src/rio.h --- redis-2.6.12/src/rio.h 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/src/rio.h 2013-04-30 13:15:56.000000000 +0000 @@ -43,10 +43,11 @@ 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. */ + /* 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 */ @@ -60,6 +61,8 @@ } buffer; struct { FILE *fp; + off_t buffered; /* Bytes written since last fsync. */ + off_t autosync; /* fsync after 'autosync' bytes written. */ } file; } io; }; @@ -96,5 +99,6 @@ size_t rioWriteBulkDouble(rio *r, double d); void rioGenericUpdateChecksum(rio *r, const void *buf, size_t len); +void rioSetAutoSync(rio *r, off_t bytes); #endif diff -Nru redis-2.6.12/src/sentinel.c redis-2.6.13/src/sentinel.c --- redis-2.6.12/src/sentinel.c 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/src/sentinel.c 2013-04-30 13:15:56.000000000 +0000 @@ -74,6 +74,8 @@ #define SRI_RECONF_DONE (1<<13) /* Slave synchronized with new master. */ #define SRI_FORCE_FAILOVER (1<<14) /* Force failover with master up. */ #define SRI_SCRIPT_KILL_SENT (1<<15) /* SCRIPT KILL already sent on -BUSY */ +#define SRI_DEMOTE (1<<16) /* If the instance claims to be a master, demote + it into a slave sending SLAVEOF. */ #define SENTINEL_INFO_PERIOD 10000 #define SENTINEL_PING_PERIOD 1000 @@ -403,7 +405,7 @@ /* Initialize various data structures. */ sentinel.masters = dictCreate(&instancesDictType,NULL); sentinel.tilt = 0; - sentinel.tilt_start_time = mstime(); + sentinel.tilt_start_time = 0; sentinel.previous_time = mstime(); sentinel.running_scripts = 0; sentinel.scripts_queue = listCreate(); @@ -1130,7 +1132,6 @@ * TODO: make this reset so that original sentinels are re-added with * same ip / port / runid. */ - int sentinelResetMasterAndChangeAddress(sentinelRedisInstance *master, char *ip, int port) { sentinelAddr *oldaddr, *newaddr; @@ -1139,12 +1140,26 @@ sentinelResetMaster(master,SENTINEL_NO_FLAGS); oldaddr = master->addr; master->addr = newaddr; + master->o_down_since_time = 0; + master->s_down_since_time = 0; + /* Release the old address at the end so we are safe even if the function * gets the master->addr->ip and master->addr->port as arguments. */ releaseSentinelAddr(oldaddr); return REDIS_OK; } +/* Return non-zero if there was no SDOWN or ODOWN error associated to this + * instance in the latest 'ms' milliseconds. */ +int sentinelRedisInstanceNoDownFor(sentinelRedisInstance *ri, mstime_t ms) { + mstime_t most_recent; + + most_recent = ri->s_down_since_time; + if (ri->o_down_since_time > most_recent) + most_recent = ri->o_down_since_time; + return most_recent == 0 || (mstime() - most_recent) > ms; +} + /* ============================ Config handling ============================= */ char *sentinelHandleConfiguration(char **argv, int argc) { sentinelRedisInstance *ri; @@ -1401,7 +1416,7 @@ * otherwise add it. */ if (sentinelRedisInstanceLookupSlave(ri,ip,atoi(port)) == NULL) { if ((slave = createSentinelRedisInstance(NULL,SRI_SLAVE,ip, - atoi(port), ri->quorum,ri)) != NULL) + atoi(port), ri->quorum, ri)) != NULL) { sentinelEvent(REDIS_NOTICE,"+slave",slave,"%@"); } @@ -1446,44 +1461,80 @@ ri->info_refresh = mstime(); sdsfreesplitres(lines,numlines); - /* ---------------------------- Acting half ----------------------------- */ - if (sentinel.tilt) return; - - /* Act if a master turned into a slave. */ - if ((ri->flags & SRI_MASTER) && role == SRI_SLAVE) { - if ((first_runid || runid_changed) && ri->slave_master_host) { - /* If it is the first time we receive INFO from it, but it's - * a slave while it was configured as a master, we want to monitor - * its master instead. */ - sentinelEvent(REDIS_WARNING,"+redirect-to-master",ri, - "%s %s %d %s %d", - ri->name, ri->addr->ip, ri->addr->port, - ri->slave_master_host, ri->slave_master_port); - sentinelResetMasterAndChangeAddress(ri,ri->slave_master_host, - ri->slave_master_port); - return; - } + /* ---------------------------- Acting half ----------------------------- + * Some things will not happen if sentinel.tilt is true, but some will + * still be processed. */ + + /* When what we believe is our master, turned into a slave, the wiser + * thing we can do is to follow the events and redirect to the new + * master, always. */ + if ((ri->flags & SRI_MASTER) && role == SRI_SLAVE && ri->slave_master_host) + { + sentinelEvent(REDIS_WARNING,"+redirect-to-master",ri, + "%s %s %d %s %d", + ri->name, ri->addr->ip, ri->addr->port, + ri->slave_master_host, ri->slave_master_port); + sentinelResetMasterAndChangeAddress(ri,ri->slave_master_host, + ri->slave_master_port); + return; /* Don't process anything after this event. */ } - /* Act if a slave turned into a master. */ + /* Handle slave -> master role switch. */ if ((ri->flags & SRI_SLAVE) && role == SRI_MASTER) { - if (!(ri->master->flags & SRI_FAILOVER_IN_PROGRESS) && - (runid_changed || first_runid)) + if (!sentinel.tilt && ri->flags & SRI_DEMOTE) { + /* If this sentinel was partitioned from the slave's master, + * or tilted recently, wait some time before to act, + * so that DOWN and roles INFO will be refreshed. */ + mstime_t wait_time = SENTINEL_INFO_PERIOD*2 + + ri->master->down_after_period*2; + + if (!sentinelRedisInstanceNoDownFor(ri->master,wait_time) || + (mstime()-sentinel.tilt_start_time) < wait_time) + return; + + /* Old master returned back? Turn it into a slave ASAP if + * we can reach what we believe is the new master now, and + * have a recent role information for it. + * + * Note: we'll clear the DEMOTE flag only when we have the + * acknowledge that it's a slave again. */ + if (ri->master->flags & SRI_MASTER && + (ri->master->flags & (SRI_S_DOWN|SRI_O_DOWN)) == 0 && + (mstime() - ri->master->info_refresh) < SENTINEL_INFO_PERIOD*2) + { + int retval; + retval = redisAsyncCommand(ri->cc, + sentinelDiscardReplyCallback, NULL, "SLAVEOF %s %d", + ri->master->addr->ip, + ri->master->addr->port); + if (retval == REDIS_OK) + sentinelEvent(REDIS_NOTICE,"+demote-old-slave",ri,"%@"); + } else { + /* Otherwise if there are not the conditions to demote, we + * no longer trust the DEMOTE flag and remove it. */ + ri->flags &= ~SRI_DEMOTE; + sentinelEvent(REDIS_NOTICE,"-demote-flag-cleared",ri,"%@"); + } + } else if (!(ri->master->flags & SRI_FAILOVER_IN_PROGRESS) && + (runid_changed || first_runid)) { /* If a slave turned into master but: * * 1) Failover not in progress. - * 2) RunID hs changed, or its the first time we see an INFO output. + * 2) RunID has changed or its the first time we see an INFO output. * * We assume this is a reboot with a wrong configuration. - * Log the event and remove the slave. */ + * Log the event and remove the slave. Note that this is processed + * in tilt mode as well, otherwise we lose the information that the + * runid changed (reboot?) and when the tilt mode ends a fake + * failover will be detected. */ int retval; sentinelEvent(REDIS_WARNING,"-slave-restart-as-master",ri,"%@ #removing it from the attached slaves"); retval = dictDelete(ri->master->slaves,ri->name); redisAssert(retval == REDIS_OK); return; - } else if (ri->flags & SRI_PROMOTED) { + } else if (!sentinel.tilt && ri->flags & SRI_PROMOTED) { /* If this is a promoted slave we can change state to the * failover state machine. */ if ((ri->master->flags & SRI_FAILOVER_IN_PROGRESS) && @@ -1499,11 +1550,12 @@ sentinelCallClientReconfScript(ri->master,SENTINEL_LEADER, "start",ri->master->addr,ri->addr); } - } else if (!(ri->master->flags & SRI_FAILOVER_IN_PROGRESS) || - ((ri->master->flags & SRI_FAILOVER_IN_PROGRESS) && - (ri->master->flags & SRI_I_AM_THE_LEADER) && - ri->master->failover_state == - SENTINEL_FAILOVER_STATE_WAIT_START)) + } else if (!sentinel.tilt && ( + !(ri->master->flags & SRI_FAILOVER_IN_PROGRESS) || + ((ri->master->flags & SRI_FAILOVER_IN_PROGRESS) && + (ri->master->flags & SRI_I_AM_THE_LEADER) && + ri->master->failover_state == + SENTINEL_FAILOVER_STATE_WAIT_START))) { /* No failover in progress? Then it is the start of a failover * and we are an observer. @@ -1523,6 +1575,7 @@ ri->master->failover_state_change_time = mstime(); ri->master->promoted_slave = ri; ri->flags |= SRI_PROMOTED; + ri->flags &= ~SRI_DEMOTE; sentinelCallClientReconfScript(ri->master,SENTINEL_OBSERVER, "start", ri->master->addr,ri->addr); /* We are an observer, so we can only assume that the leader @@ -1534,6 +1587,10 @@ } } + /* None of the following conditions are processed when in tilt mode, so + * return asap. */ + if (sentinel.tilt) return; + /* Detect if the slave that is in the process of being reconfigured * changed state. */ if ((ri->flags & SRI_SLAVE) && role == SRI_SLAVE && @@ -1564,6 +1621,13 @@ ri->failover_state_change_time = mstime(); } } + + /* Detect if the old master was demoted as slave and generate the + * +slave event. */ + if (role == SRI_SLAVE && ri->flags & SRI_DEMOTE) { + sentinelEvent(REDIS_NOTICE,"+slave",ri,"%@"); + ri->flags &= ~SRI_DEMOTE; + } } void sentinelInfoReplyCallback(redisAsyncContext *c, void *reply, void *privdata) { @@ -1835,6 +1899,7 @@ if (ri->flags & SRI_RECONF_SENT) flags = sdscat(flags,"reconf_sent,"); if (ri->flags & SRI_RECONF_INPROG) flags = sdscat(flags,"reconf_inprog,"); if (ri->flags & SRI_RECONF_DONE) flags = sdscat(flags,"reconf_done,"); + if (ri->flags & SRI_DEMOTE) flags = sdscat(flags,"demote,"); if (sdslen(flags) != 0) flags = sdsrange(flags,0,-2); /* remove last "," */ addReplyBulkCString(c,flags); @@ -2592,6 +2657,7 @@ mstime_t info_validity_time = mstime()-SENTINEL_INFO_VALIDITY_TIME; if (slave->flags & (SRI_S_DOWN|SRI_O_DOWN|SRI_DISCONNECTED)) continue; + if (slave->flags & SRI_DEMOTE) continue; /* Old master not yet ready. */ if (slave->last_avail_time < info_validity_time) continue; if (slave->slave_priority == 0) continue; @@ -2837,12 +2903,28 @@ void sentinelFailoverSwitchToPromotedSlave(sentinelRedisInstance *master) { sentinelRedisInstance *ref = master->promoted_slave ? master->promoted_slave : master; + sds old_master_ip; + int old_master_port; sentinelEvent(REDIS_WARNING,"+switch-master",master,"%s %s %d %s %d", master->name, master->addr->ip, master->addr->port, ref->addr->ip, ref->addr->port); + old_master_ip = sdsdup(master->addr->ip); + old_master_port = master->addr->port; sentinelResetMasterAndChangeAddress(master,ref->addr->ip,ref->addr->port); + /* If this is a real switch, that is, we have master->promoted_slave not + * NULL, then we want to add the old master as a slave of the new master, + * but flagging it with SRI_DEMOTE so that we know we'll need to send + * SLAVEOF once the old master is reachable again. */ + if (master != ref) { + /* Add the new slave, but don't generate a Sentinel event as it will + * happen later when finally the instance will claim to be a slave + * in the INFO output. */ + createSentinelRedisInstance(NULL,SRI_SLAVE|SRI_DEMOTE, + old_master_ip, old_master_port, master->quorum, master); + } + sdsfree(old_master_ip); } void sentinelFailoverStateMachine(sentinelRedisInstance *ri) { diff -Nru redis-2.6.12/src/version.h redis-2.6.13/src/version.h --- redis-2.6.12/src/version.h 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/src/version.h 2013-04-30 13:15:56.000000000 +0000 @@ -1 +1 @@ -#define REDIS_VERSION "2.6.12" +#define REDIS_VERSION "2.6.13" diff -Nru redis-2.6.12/tests/assets/default.conf redis-2.6.13/tests/assets/default.conf --- redis-2.6.12/tests/assets/default.conf 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/tests/assets/default.conf 2013-04-30 13:15:56.000000000 +0000 @@ -1,344 +1,23 @@ -# Redis configuration file example +# Redis configuration for testing. -# Note on units: when memory size is needed, it is possible to specifiy -# it in the usual form of 1k 5GB 4M and so forth: -# -# 1k => 1000 bytes -# 1kb => 1024 bytes -# 1m => 1000000 bytes -# 1mb => 1024*1024 bytes -# 1g => 1000000000 bytes -# 1gb => 1024*1024*1024 bytes -# -# units are case insensitive so 1GB 1Gb 1gB are all the same. - -# By default Redis does not run as a daemon. Use 'yes' if you need it. -# Note that Redis will write a pid file in /var/run/redis.pid when daemonized. daemonize no - -# When running daemonized, Redis writes a pid file in /var/run/redis.pid by -# default. You can specify a custom pid file location here. pidfile /var/run/redis.pid - -# Accept connections on the specified port, default is 6379. port 6379 - -# If you want you can bind a single interface, if the bind option is not -# specified all the interfaces will listen for incoming connections. -# -# bind 127.0.0.1 - -# Specify the path for the unix socket that will be used to listen for -# incoming connections. There is no default, so Redis will not listen -# on a unix socket when not specified. -# -# unixsocket /tmp/redis.sock - -# Close the connection after a client is idle for N seconds (0 to disable) timeout 0 - -# Set server verbosity to 'debug' -# it can be one of: -# debug (a lot of information, useful for development/testing) -# verbose (many rarely useful info, but not a mess like the debug level) -# notice (moderately verbose, what you want in production probably) -# warning (only very important / critical messages are logged) loglevel verbose - -# Specify the log file name. Also 'stdout' can be used to force -# Redis to log on the standard output. Note that if you use standard -# output for logging but daemonize, logs will be sent to /dev/null logfile stdout - -# To enable logging to the system logger, just set 'syslog-enabled' to yes, -# and optionally update the other syslog parameters to suit your needs. -# syslog-enabled no - -# Specify the syslog identity. -# syslog-ident redis - -# Specify the syslog facility. Must be USER or between LOCAL0-LOCAL7. -# syslog-facility local0 - -# Set the number of databases. The default database is DB 0, you can select -# a different one on a per-connection basis using SELECT where -# dbid is a number between 0 and 'databases'-1 databases 16 -################################ SNAPSHOTTING ################################# -# -# Save the DB on disk: -# -# save -# -# Will save the DB if both the given number of seconds and the given -# number of write operations against the DB occurred. -# -# In the example below the behaviour will be to save: -# after 900 sec (15 min) if at least 1 key changed -# after 300 sec (5 min) if at least 10 keys changed -# after 60 sec if at least 10000 keys changed -# -# Note: you can disable saving at all commenting all the "save" lines. - save 900 1 save 300 10 save 60 10000 -# Compress string objects using LZF when dump .rdb databases? -# For default that's set to 'yes' as it's almost always a win. -# If you want to save some CPU in the saving child set it to 'no' but -# the dataset will likely be bigger if you have compressible values or keys. rdbcompression yes - -# The filename where to dump the DB dbfilename dump.rdb - -# The working directory. -# -# The DB will be written inside this directory, with the filename specified -# above using the 'dbfilename' configuration directive. -# -# Also the Append Only File will be created inside this directory. -# -# Note that you must specify a directory here, not a file name. dir ./ -################################# REPLICATION ################################# - -# Master-Slave replication. Use slaveof to make a Redis instance a copy of -# another Redis server. Note that the configuration is local to the slave -# so for example it is possible to configure the slave to save the DB with a -# different interval, or to listen to another port, and so on. -# -# slaveof - -# If the master is password protected (using the "requirepass" configuration -# directive below) it is possible to tell the slave to authenticate before -# starting the replication synchronization process, otherwise the master will -# refuse the slave request. -# -# masterauth - -# When a slave lost the connection with the master, or when the replication -# is still in progress, the slave can act in two different ways: -# -# 1) if slave-serve-stale-data is set to 'yes' (the default) the slave will -# still reply to client requests, possibly with out of data data, or the -# data set may just be empty if this is the first synchronization. -# -# 2) if slave-serve-stale data is set to 'no' the slave will reply with -# an error "SYNC with master in progress" to all the kind of commands -# but to INFO and SLAVEOF. -# slave-serve-stale-data yes - -################################## SECURITY ################################### - -# Require clients to issue AUTH before processing any other -# commands. This might be useful in environments in which you do not trust -# others with access to the host running redis-server. -# -# This should stay commented out for backward compatibility and because most -# people do not need auth (e.g. they run their own servers). -# -# Warning: since Redis is pretty fast an outside user can try up to -# 150k passwords per second against a good box. This means that you should -# use a very strong password otherwise it will be very easy to break. -# -# requirepass foobared - -# Command renaming. -# -# It is possilbe to change the name of dangerous commands in a shared -# environment. For instance the CONFIG command may be renamed into something -# of hard to guess so that it will be still available for internal-use -# tools but not available for general clients. -# -# Example: -# -# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52 -# -# It is also possilbe to completely kill a command renaming it into -# an empty string: -# -# rename-command CONFIG "" - -################################### LIMITS #################################### - -# Set the max number of connected clients at the same time. By default there -# is no limit, and it's up to the number of file descriptors the Redis process -# is able to open. The special value '0' means no limits. -# Once the limit is reached Redis will close all the new connections sending -# an error 'max number of clients reached'. -# -# maxclients 128 - -# Don't use more memory than the specified amount of bytes. -# When the memory limit is reached Redis will try to remove keys with an -# EXPIRE set. It will try to start freeing keys that are going to expire -# in little time and preserve keys with a longer time to live. -# Redis will also try to remove objects from free lists if possible. -# -# If all this fails, Redis will start to reply with errors to commands -# that will use more memory, like SET, LPUSH, and so on, and will continue -# to reply to most read-only commands like GET. -# -# WARNING: maxmemory can be a good idea mainly if you want to use Redis as a -# 'state' server or cache, not as a real DB. When Redis is used as a real -# database the memory usage will grow over the weeks, it will be obvious if -# it is going to use too much memory in the long run, and you'll have the time -# to upgrade. With maxmemory after the limit is reached you'll start to get -# errors for write operations, and this may even lead to DB inconsistency. -# -# maxmemory - -# MAXMEMORY POLICY: how Redis will select what to remove when maxmemory -# is reached? You can select among five behavior: -# -# volatile-lru -> remove the key with an expire set using an LRU algorithm -# allkeys-lru -> remove any key accordingly to the LRU algorithm -# volatile-random -> remove a random key with an expire set -# allkeys->random -> remove a random key, any key -# volatile-ttl -> remove the key with the nearest expire time (minor TTL) -# noeviction -> don't expire at all, just return an error on write operations -# -# Note: with all the kind of policies, Redis will return an error on write -# operations, when there are not suitable keys for eviction. -# -# At the date of writing this commands are: set setnx setex append -# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd -# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby -# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby -# getset mset msetnx exec sort -# -# The default is: -# -# maxmemory-policy volatile-lru - -# LRU and minimal TTL algorithms are not precise algorithms but approximated -# algorithms (in order to save memory), so you can select as well the sample -# size to check. For instance for default Redis will check three keys and -# pick the one that was used less recently, you can change the sample size -# using the following configuration directive. -# -# maxmemory-samples 3 - -############################## APPEND ONLY MODE ############################### - -# By default Redis asynchronously dumps the dataset on disk. If you can live -# with the idea that the latest records will be lost if something like a crash -# happens this is the preferred way to run Redis. If instead you care a lot -# about your data and don't want to that a single record can get lost you should -# enable the append only mode: when this mode is enabled Redis will append -# every write operation received in the file appendonly.aof. This file will -# be read on startup in order to rebuild the full dataset in memory. -# -# Note that you can have both the async dumps and the append only file if you -# like (you have to comment the "save" statements above to disable the dumps). -# Still if append only mode is enabled Redis will load the data from the -# log file at startup ignoring the dump.rdb file. -# -# IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append -# log file in background when it gets too big. - appendonly no - -# The name of the append only file (default: "appendonly.aof") -# appendfilename appendonly.aof - -# The fsync() call tells the Operating System to actually write data on disk -# instead to wait for more data in the output buffer. Some OS will really flush -# data on disk, some other OS will just try to do it ASAP. -# -# Redis supports three different modes: -# -# no: don't fsync, just let the OS flush the data when it wants. Faster. -# always: fsync after every write to the append only log . Slow, Safest. -# everysec: fsync only if one second passed since the last fsync. Compromise. -# -# The default is "everysec" that's usually the right compromise between -# speed and data safety. It's up to you to understand if you can relax this to -# "no" that will will let the operating system flush the output buffer when -# it wants, for better performances (but if you can live with the idea of -# some data loss consider the default persistence mode that's snapshotting), -# or on the contrary, use "always" that's very slow but a bit safer than -# everysec. -# -# If unsure, use "everysec". - -# appendfsync always appendfsync everysec -# appendfsync no - -# When the AOF fsync policy is set to always or everysec, and a background -# saving process (a background save or AOF log background rewriting) is -# performing a lot of I/O against the disk, in some Linux configurations -# Redis may block too long on the fsync() call. Note that there is no fix for -# this currently, as even performing fsync in a different thread will block -# our synchronous write(2) call. -# -# In order to mitigate this problem it's possible to use the following option -# that will prevent fsync() from being called in the main process while a -# BGSAVE or BGREWRITEAOF is in progress. -# -# This means that while another child is saving the durability of Redis is -# the same as "appendfsync none", that in pratical terms means that it is -# possible to lost up to 30 seconds of log in the worst scenario (with the -# default Linux settings). -# -# If you have latency problems turn this to "yes". Otherwise leave it as -# "no" that is the safest pick from the point of view of durability. no-appendfsync-on-rewrite no - -############################### ADVANCED CONFIG ############################### - -# Hashes are encoded in a special way (much more memory efficient) when they -# have at max a given numer of elements, and the biggest element does not -# exceed a given threshold. You can configure this limits with the following -# configuration directives. -hash-max-ziplist-entries 64 -hash-max-ziplist-value 512 - -# Similarly to hashes, small lists are also encoded in a special way in order -# to save a lot of space. The special representation is only used when -# you are under the following limits: -list-max-ziplist-entries 512 -list-max-ziplist-value 64 - -# Sets have a special encoding in just one case: when a set is composed -# of just strings that happens to be integers in radix 10 in the range -# of 64 bit signed integers. -# The following configuration setting sets the limit in the size of the -# set in order to use this special memory saving encoding. -set-max-intset-entries 512 - -# Active rehashing uses 1 millisecond every 100 milliseconds of CPU time in -# order to help rehashing the main Redis hash table (the one mapping top-level -# keys to values). The hash table implementation redis uses (see dict.c) -# performs a lazy rehashing: the more operation you run into an hash table -# that is rhashing, the more rehashing "steps" are performed, so if the -# server is idle the rehashing is never complete and some more memory is used -# by the hash table. -# -# The default is to use this millisecond 10 times every second in order to -# active rehashing the main dictionaries, freeing memory when possible. -# -# If unsure: -# use "activerehashing no" if you have hard latency requirements and it is -# not a good thing in your environment that Redis can reply form time to time -# to queries with 2 milliseconds delay. -# -# use "activerehashing yes" if you don't have such hard requirements but -# want to free memory asap when possible. activerehashing yes - -################################## INCLUDES ################################### - -# Include one or more other config files here. This is useful if you -# have a standard template that goes to all redis server but also need -# to customize a few per-server settings. Include files can include -# other files, so use this wisely. -# -# include /path/to/local.conf -# include /path/to/other.conf diff -Nru redis-2.6.12/tests/integration/rdb.tcl redis-2.6.13/tests/integration/rdb.tcl --- redis-2.6.12/tests/integration/rdb.tcl 2013-03-29 16:42:39.000000000 +0000 +++ redis-2.6.13/tests/integration/rdb.tcl 2013-04-30 13:15:56.000000000 +0000 @@ -53,18 +53,31 @@ # Make the RDB file unreadable file attributes [file join $server_path dump.rdb] -permissions 0222 +# Detect root account (it is able to read the file even with 002 perm) +set isroot 0 +catch { + open [file join $server_path dump.rdb] + set isroot 1 +} + # Now make sure the server aborted with an error -start_server_and_kill_it [list "dir" $server_path] { - wait_for_condition 50 100 { - [string match {*Fatal error loading*} \ - [exec tail -n1 < [dict get $srv stdout]]] - } else { - fail "Server started even if RDB was unreadable!" +if {!$isroot} { + start_server_and_kill_it [list "dir" $server_path] { + test {Server should not start if RDB file can't be open} { + wait_for_condition 50 100 { + [string match {*Fatal error loading*} \ + [exec tail -n1 < [dict get $srv stdout]]] + } else { + fail "Server started even if RDB was unreadable!" + } + } } } -# Fix permissions of the RDB file, but corrupt its CRC64 checksum. +# Fix permissions of the RDB file. file attributes [file join $server_path dump.rdb] -permissions 0666 + +# Corrupt its CRC64 checksum. set filesize [file size [file join $server_path dump.rdb]] set fd [open [file join $server_path dump.rdb] r+] fconfigure $fd -translation binary @@ -74,10 +87,12 @@ # Now make sure the server aborted with an error start_server_and_kill_it [list "dir" $server_path] { - wait_for_condition 50 100 { - [string match {*RDB checksum*} \ - [exec tail -n1 < [dict get $srv stdout]]] - } else { - fail "Server started even if RDB was corrupted!" + test {Server should not start if RDB is corrupted} { + wait_for_condition 50 100 { + [string match {*RDB checksum*} \ + [exec tail -n1 < [dict get $srv stdout]]] + } else { + fail "Server started even if RDB was corrupted!" + } } }