diff --git a/README b/README deleted file mode 100644 index 369118631149..000000000000 --- a/README +++ /dev/null @@ -1,173 +0,0 @@ -Where to find complete Redis documentation? -------------------------------------------- - -This README is just a fast "quick start" document. You can find more detailed -documentation at http://redis.io - -Building Redis --------------- - -Redis can be compiled and used on Linux, OSX, OpenBSD, NetBSD, FreeBSD. -We support big endian and little endian architectures. - -It may compile on Solaris derived systems (for instance SmartOS) but our -support for this platform is "best effort" and Redis is not guaranteed to -work as well as in Linux, OSX, and *BSD there. - -It is as simple as: - - % make - -You can run a 32 bit Redis binary using: - - % make 32bit - -After building Redis is a good idea to test it, using: - - % make test - -Fixing build problems with dependencies or cached build options -—-------- -Redis has some dependencies which are included into the "deps" directory. -"make" does not rebuild dependencies automatically, even if something in the -source code of dependencies is changes. - -When you update the source code with `git pull` or when code inside the -dependencies tree is modified in any other way, make sure to use the following -command in order to really clean everything and rebuild from scratch: - - make distclean - -This will clean: jemalloc, lua, hiredis, linenoise. - -Also if you force certain build options like 32bit target, no C compiler -optimizations (for debugging purposes), and other similar build time options, -those options are cached indefinitely until you issue a "make distclean" -command. - -Fixing problems building 32 bit binaries ---------- - -If after building Redis with a 32 bit target you need to rebuild it -with a 64 bit target, or the other way around, you need to perform a -"make distclean" in the root directory of the Redis distribution. - -In case of build errors when trying to build a 32 bit binary of Redis, try -the following steps: - -* Install the packages libc6-dev-i386 (also try g++-multilib). -* Try using the following command line instead of "make 32bit": - - make CFLAGS="-m32 -march=native" LDFLAGS="-m32" - -Allocator ---------- - -Selecting a non-default memory allocator when building Redis is done by setting -the `MALLOC` environment variable. Redis is compiled and linked against libc -malloc by default, with the exception of jemalloc being the default on Linux -systems. This default was picked because jemalloc has proven to have fewer -fragmentation problems than libc malloc. - -To force compiling against libc malloc, use: - - % make MALLOC=libc - -To compile against jemalloc on Mac OS X systems, use: - - % make MALLOC=jemalloc - -Verbose build -------------- - -Redis will build with a user friendly colorized output by default. -If you want to see a more verbose output use the following: - - % make V=1 - -Running Redis -------------- - -To run Redis with the default configuration just type: - - % cd src - % ./redis-server - -If you want to provide your redis.conf, you have to run it using an additional -parameter (the path of the configuration file): - - % cd src - % ./redis-server /path/to/redis.conf - -It is possible to alter the Redis configuration passing parameters directly -as options using the command line. Examples: - - % ./redis-server --port 9999 --slaveof 127.0.0.1 6379 - % ./redis-server /etc/redis/6379.conf --loglevel debug - -All the options in redis.conf are also supported as options using the command -line, with exactly the same name. - -Playing with Redis ------------------- - -You can use redis-cli to play with Redis. Start a redis-server instance, -then in another terminal try the following: - - % cd src - % ./redis-cli - redis> ping - PONG - redis> set foo bar - OK - redis> get foo - "bar" - redis> incr mycounter - (integer) 1 - redis> incr mycounter - (integer) 2 - redis> - -You can find the list of all the available commands here: - - http://redis.io/commands - -Installing Redis ------------------ - -In order to install Redis binaries into /usr/local/bin just use: - - % make install - -You can use "make PREFIX=/some/other/directory install" if you wish to use a -different destination. - -Make install will just install binaries in your system, but will not configure -init scripts and configuration files in the appropriate place. This is not -needed if you want just to play a bit with Redis, but if you are installing -it the proper way for a production system, we have a script doing this -for Ubuntu and Debian systems: - - % cd utils - % ./install_server.sh - -The script will ask you a few questions and will setup everything you need -to run Redis properly as a background daemon that will start again on -system reboots. - -You'll be able to stop and start Redis using the script named -/etc/init.d/redis_, for instance /etc/init.d/redis_6379. - -Code contributions ---- - -Note: by contributing code to the Redis project in any form, including sending -a pull request via Github, a code fragment or patch via private email or -public discussion groups, you agree to release your code under the terms -of the BSD license that you can find in the COPYING file included in the Redis -source distribution. - -Please see the CONTRIBUTING file in this source distribution for more -information. - -Enjoy! diff --git a/README.md b/README.md index d015d33bb010..e68aeef99501 100644 --- a/README.md +++ b/README.md @@ -17,22 +17,24 @@ Redis on Windows - Signed binaries can be downloaded using Nuget and Chocolatey. - There is a replacement for the UNIX fork() API that simulates the copy-on-write behavior using a memory mapped file. - Because Redis makes some assumptions about the values of File Descriptors, we have built a virtual file descriptor mapping layer. -- We are moving towards moving all Windows-specific changes into the Win32_Interop library. - Redis can be installed as a Windows Service. -## What's new since 2.8.12 +## Redis 2.8 release notes -- See the Redis release notes: http://download.redis.io/redis-stable/00-RELEASENOTES +- Redis on UNIX [release notes](https://raw.githubusercontent.com/antirez/redis/2.8/00-RELEASENOTES) +- Redis on Windows [release notes](https://raw.githubusercontent.com/MSOpenTech/redis/2.8/Redis%20on%20Windows%20Release%20Notes.md) -## Important: More documentation is available +## How to configure and deploy Redis on Windows -Please read the documentation in msvs\setups\documentation. This is the documentation that is bundled with the binaries, and contains vital information about configuring and deploying Redis on Windows. +- [Memory Configuration](https://github.com/MSOpenTech/redis/wiki/Memory-Configuration "Memory Configuration") +- [Redis on Windows](https://raw.githubusercontent.com/MSOpenTech/redis/2.8/Redis%20on%20Windows.md "Redis on Windows") +- [Windows Service Documentation](https://raw.githubusercontent.com/MSOpenTech/redis/2.8/Windows%20Service%20Documentation.md "Windows Service Documentation") ## How to build Redis using Visual Studio You can use the free Visual Studio Community edition available at http://www.visualstudio.com/products/visual-studio-community-vs. -- Open the solution file msvs\redisserver.sln in Visual Studio, select a build configuration (Debug or Release) and target (Win32 or x64) then build. +- Open the solution file msvs\redisserver.sln in Visual Studio, select a build configuration (Debug or Release) and target (x64) then build. This should create the following executables in the msvs\$(Target)\$(Configuration) folder: @@ -52,21 +54,6 @@ To run the Redis test suite requires some manual work: - To run the tests you need to have a Unix shell on your machine, or MinGW tools in your path. To execute the tests, run the following command: "tclsh8.5.exe tests/test_helper.tcl --clients N", where N is the number of parallel clients . If a Unix shell is not installed you may see the following error message: "couldn't execute "cat": no such file or directory". -- By default the test suite launches 16 parallel tests. I will get time out errors on an iCore 7-2620m@2.7Ghz with some of the tests when the number of clients - is greater than 6. +- By default the test suite launches 16 parallel tests, but some of the tests may fail when the number of clients is greater than 2. -## Known issues - -Problem: -On versions of Windows prior to Windows 8/Server 2012, when an AOF or RDB operation is complete and the child process is being rejoined with the parent, it is -possible for Redis to unexpectedly terminate. - -Cause: -The PAGE_REVERT_TO_FILE_MAP flag is not usable in VirtualProtect() in earlier versions of the OS. This flag allows for removing copy on write(COW) pages from -a memory mapped view without unmapping the view. In prior versions of the OS, the only way to purge COW pages is to unmap and then remap the memory mapped view. -Between the unmapping and remapping operations a third party process(e.g., an anti-virus program) could allocate virtual memory occupied by the memory mapped view. -As this view is used for the Redis heap, failure to remap is a fatal error. (See RejoinCOWPages() in src\Win32_Interop\Win32_QFork.cpp) - -Solution: -If you encounter this problem, host Redis on Windows 8/Server 2012 or newer. diff --git a/Redis on Windows Release Notes.md b/Redis on Windows Release Notes.md index 465fc2841464..48b82b500c90 100644 --- a/Redis on Windows Release Notes.md +++ b/Redis on Windows Release Notes.md @@ -1,34 +1,61 @@ -MSOpenTech Redis 2.8.20 Release Notes -===================================== +MSOpenTech Redis on Windows 2.8 Release Notes +============================================= -Welcome to the binary release of Redis from Microsoft Open Technologies, Inc. +--[ Redis on Windows 2.8.21 ] Release date: Jun 24 2015 -What is Redis? --------------- + - Merged Redis 2.8.21 [https://raw.githubusercontent.com/antirez/redis/2.8/00-RELEASENOTES] + - Fixes for 64-bit portability. + - Fixed rejoin pages on COW race condition. + - Fixed AOF truncation. + - Fixed crash when the 'save' flag is set and the 'persistence-available' flag is set to 'no'. + - Logging a BUG REPORT (stack trace and server info) when Redis crashes. + - Restored native Redis command arguments: -h, --help, -version, --version, --test-memory. + - Install symbols for redis binaries. + - Prevent firewall exception from being added if the Windows Firewall Windows service is stopped. (NickMRamirez) + - Fix wrong pointer castings for x64 support. (zeliard) + - Fix pointer casting for supporting a 64bit case. (zeliard) + - Fix wrong memset argument. (zeliard) -Redis is an open source, high performance, key-value store. Values may contain strings, hashes, lists, sets and sorted sets. Redis has been developed primarily for UNIX-like operating systems. +--[ Redis on Windows 2.8.19.1 ] Release date: May 04 2015 -Porting Goals -------------- + - Added an MSI installer, in addition to the .zip distribution + - Various bug fixes, including: + #167 + #228 -Our goal is to provide a version of Redis that runs on Windows with a performance essentially equal to the performance of Redis on an equivalent UNIX machine. +--[ Redis on Windows 2.8.19 ] Release date: Feb 25 2015 -What is new with the 2.8.20 release ------------------------------------ + - Workaround for getpeername() issue, which affected sentinel failover over ipv6. + - Miscellaneous bug fixes. -Our last official release was 2.8.12. We have merged in the changes up to 2.8.20. Please see the [release notes for the UNIX 2.8 branch](http://download.redis.io/redis-stable/00-RELEASENOTES) to understand how this impacts Redis functionality. +--[ Redis on Windows 2.8.17.4 ] Release date: Feb 02 2015 -### Network layer changes + - Fix AV in AllocHeapBlock. -There have been significant changes to the networking layer for this version. Likely there will be a few weeks before there is another official (Chocolatey and Nuget) release. Most of these changes target IPv6. +--[ Redis on Windows 2.8.17.3 ] Release date: Dec 26 2014 -### persistence-available flag + - Fix redis-cli pipe mode. -If Redis is to be used as an in-memory-only cache without any kind of persistence, then the fork() mechanism used by the background AOF/RDB persistence is unnecessary. As an optimization, all persistence can be turned off in the Windows version of Redis in this scenario. This will disable the creation of the memory mapped heap file, redirect heap allocations to the system heap allocator, and disable commands that would otherwise cause fork() operations: BGSAVE and BGREWRITEAOF. This flag may not be combined with any of the other flags that configure AOF and RDB operations. +--[ Redis on Windows 2.8.17.2 ] Release date: Dec 23 2014 -persistence-available [(yes)|no] + - Moved binaries out of the repository, to the Releases page. + - Miscellaneous bug fixes. -How to develop for Redis ------------------------- +--[ Redis on Windows 2.8.17.1 ] Release date: Dec 16 2014 -You will need a client library for accessing Redis. There are a wide variety of client libraries available as listed at . + - Move release binaries to release page. + - Adopting the suggestions at #172. + - We no longer commit the binaries into the repo. + - Instead, we create periodic releases on the release page. + +--[ Redis on Windows 2.8.12 ] Release date: Sep 4 2014 + +--[ Redis on Windows 2.8.9 ] Release date: Jun 26 2014 + +--[ Redis on Windows 2.6.14 ] Release date: May 20 2014 + +--[ Redis on Windows 2.8.4 ] Release date: May 20 2014 + +--[ Redis on Windows 2.6.8 ] Release date: May 6 2013 + +--[ Redis on Windows 2.4.6 ] Release date: Feb 10 2012 diff --git a/Redis on Windows.md b/Redis on Windows.md index fc5283788d41..25802f69b4c4 100644 --- a/Redis on Windows.md +++ b/Redis on Windows.md @@ -1,6 +1,8 @@ MSOpenTech’s Redis on Windows ============================= +Redis is an open source, high performance, key-value store. Values may contain strings, hashes, lists, sets and sorted sets. Redis has been developed primarily for UNIX-like operating systems. +Our goal is to provide a version of Redis that runs on Windows with a performance essentially equal to the performance of Redis on an equivalent UNIX machine. We strive to have a stable, functionally equivalent and comparably performing version of Redis on Windows. We have achieved performance nearly identical to the POSIX version running head-to-head on identical hardware across the network. Aside from feature differences that help Redis take advantage of the Windows infrastructure, our version of Redis should work in most situations with the identical setup and configuration that one would use on a POSIX operating system. How is Redis on Windows implemented? @@ -105,3 +107,8 @@ Service Account --------------- When using Redis as a Windows service, the default installation configures Redis to run under the system’s NETWORK SERVICE account. There are some environments where another account must be used (perhaps a domain service account). Configuration of this account needs to be done manually at this point with the service control manager. If this is done, it is also important to give read/write/create permission to the folder that the Redis executable is in to this user identity. + +How to develop for Redis +======================== + +You will need a client library for accessing Redis. There are a wide variety of client libraries available as listed at . diff --git a/appveyor.yml b/appveyor.yml index d0988ada50a2..f5f621d98eaa 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.8.13.{build} +version: 2.8.21.{build} branches: # whitelist diff --git a/deps/hiredis/dict.c b/deps/hiredis/dict.c index 79d2c1c8d6f1..ccb844b0be62 100644 --- a/deps/hiredis/dict.c +++ b/deps/hiredis/dict.c @@ -34,7 +34,6 @@ */ #ifdef _WIN32 #include "../../src/win32_Interop/win32_types.h" -#include "../../src/win32_Interop/win32_util.h" #endif #include "fmacros.h" diff --git a/deps/hiredis/net.c b/deps/hiredis/net.c index c37521a29707..1b0ef0b63421 100644 --- a/deps/hiredis/net.c +++ b/deps/hiredis/net.c @@ -58,8 +58,9 @@ #include "net.h" #include "sds.h" #ifdef _WIN32 + #include "../../src/win32_Interop/win32_util.h" #include "../../src/win32_Interop/win32fixes.h" -#include "mstcpip.h" + #include "mstcpip.h" #endif /* Defined in hiredis.c */ @@ -234,7 +235,7 @@ static int redisContextWaitReady(redisContext *c, const struct timeval *timeout) if (errno == EINPROGRESS) { int res; - if ((res = poll(wfd, 1, msec)) == -1) { + if ((res = poll(wfd, 1, (int) msec)) == -1) { WIN_PORT_FIX /* cast (int) */ __redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)"); redisContextCloseFd(c); return REDIS_ERR; diff --git a/deps/lua/src/ldo.c b/deps/lua/src/ldo.c index d1bf786cb720..514f7a2a31f6 100644 --- a/deps/lua/src/ldo.c +++ b/deps/lua/src/ldo.c @@ -495,7 +495,7 @@ static void f_parser (lua_State *L, void *ud) { struct SParser *p = cast(struct SParser *, ud); int c = luaZ_lookahead(p->z); luaC_checkGC(L); - tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, + tf = (luaY_parser)(L, p->z, &p->buff, p->name); cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); cl->l.p = tf; diff --git a/deps/lua/src/lua_cmsgpack.c b/deps/lua/src/lua_cmsgpack.c index fe2e1cfaade0..e47f4af6aad5 100644 --- a/deps/lua/src/lua_cmsgpack.c +++ b/deps/lua/src/lua_cmsgpack.c @@ -66,7 +66,7 @@ /* Reverse memory bytes if arch is little endian. Given the conceptual * simplicity of the Lua build system we prefer check for endianess at runtime. * The performance difference should be acceptable. */ -static void memrevifle(void *ptr, size_t len) { +void memrevifle(void *ptr, size_t len) { unsigned char *p = (unsigned char *)ptr, *e = (unsigned char *)p+len-1, aux; @@ -96,7 +96,7 @@ typedef struct mp_buf { size_t len, free; } mp_buf; -static void *mp_realloc(lua_State *L, void *target, size_t osize,size_t nsize) { +void *mp_realloc(lua_State *L, void *target, size_t osize,size_t nsize) { void *(*local_realloc) (void *, void *, size_t osize, size_t nsize) = NULL; void *ud; @@ -105,7 +105,7 @@ static void *mp_realloc(lua_State *L, void *target, size_t osize,size_t nsize) { return local_realloc(ud, target, osize, nsize); } -static mp_buf *mp_buf_new(lua_State *L) { +mp_buf *mp_buf_new(lua_State *L) { mp_buf *buf = NULL; /* Old size = 0; new size = sizeof(*buf) */ @@ -117,7 +117,7 @@ static mp_buf *mp_buf_new(lua_State *L) { return buf; } -static void mp_buf_append(mp_buf *buf, const unsigned char *s, size_t len) { +void mp_buf_append(mp_buf *buf, const unsigned char *s, size_t len) { if (buf->free < len) { size_t newlen = buf->len+len; @@ -153,7 +153,7 @@ typedef struct mp_cur { int err; } mp_cur; -static void mp_cur_init(mp_cur *cursor, const unsigned char *s, size_t len) { +void mp_cur_init(mp_cur *cursor, const unsigned char *s, size_t len) { cursor->p = s; cursor->left = len; cursor->err = MP_CUR_ERROR_NONE; @@ -173,13 +173,17 @@ static void mp_cur_init(mp_cur *cursor, const unsigned char *s, size_t len) { /* ------------------------- Low level MP encoding -------------------------- */ -static void mp_encode_bytes(mp_buf *buf, const unsigned char *s, size_t len) { +void mp_encode_bytes(mp_buf *buf, const unsigned char *s, size_t len) { unsigned char hdr[5]; int hdrlen; if (len < 32) { hdr[0] = 0xa0 | (len&0xff); /* fix raw */ hdrlen = 1; + } else if (len <= 0xff) { + hdr[0] = 0xd9; + hdr[1] = len; + hdrlen = 2; } else if (len <= 0xffff) { hdr[0] = 0xda; hdr[1] = (len&0xff00)>>8; @@ -198,7 +202,7 @@ static void mp_encode_bytes(mp_buf *buf, const unsigned char *s, size_t len) { } /* we assume IEEE 754 internal format for single and double precision floats. */ -static void mp_encode_double(mp_buf *buf, double d) { +void mp_encode_double(mp_buf *buf, double d) { unsigned char b[9]; float f = d; @@ -216,7 +220,7 @@ static void mp_encode_double(mp_buf *buf, double d) { } } -static void mp_encode_int(mp_buf *buf, int64_t n) { +void mp_encode_int(mp_buf *buf, int64_t n) { unsigned char b[9]; int enclen; @@ -288,7 +292,7 @@ static void mp_encode_int(mp_buf *buf, int64_t n) { mp_buf_append(buf,b,enclen); } -static void mp_encode_array(mp_buf *buf, int64_t n) { +void mp_encode_array(mp_buf *buf, int64_t n) { unsigned char b[5]; int enclen; @@ -311,7 +315,7 @@ static void mp_encode_array(mp_buf *buf, int64_t n) { mp_buf_append(buf,b,enclen); } -static void mp_encode_map(mp_buf *buf, int64_t n) { +void mp_encode_map(mp_buf *buf, int64_t n) { unsigned char b[5]; int enclen; @@ -336,7 +340,7 @@ static void mp_encode_map(mp_buf *buf, int64_t n) { /* --------------------------- Lua types encoding --------------------------- */ -static void mp_encode_lua_string(lua_State *L, mp_buf *buf) { +void mp_encode_lua_string(lua_State *L, mp_buf *buf) { size_t len; const char *s; @@ -344,13 +348,13 @@ static void mp_encode_lua_string(lua_State *L, mp_buf *buf) { mp_encode_bytes(buf,(const unsigned char*)s,len); } -static void mp_encode_lua_bool(lua_State *L, mp_buf *buf) { +void mp_encode_lua_bool(lua_State *L, mp_buf *buf) { unsigned char b = lua_toboolean(L,-1) ? 0xc3 : 0xc2; mp_buf_append(buf,&b,1); } /* Lua 5.3 has a built in 64-bit integer type */ -static void mp_encode_lua_integer(lua_State *L, mp_buf *buf) { +void mp_encode_lua_integer(lua_State *L, mp_buf *buf) { #if (LUA_VERSION_NUM < 503) && BITS_32 lua_Number i = lua_tonumber(L,-1); #else @@ -362,7 +366,7 @@ static void mp_encode_lua_integer(lua_State *L, mp_buf *buf) { /* Lua 5.2 and lower only has 64-bit doubles, so we need to * detect if the double may be representable as an int * for Lua < 5.3 */ -static void mp_encode_lua_number(lua_State *L, mp_buf *buf) { +void mp_encode_lua_number(lua_State *L, mp_buf *buf) { lua_Number n = lua_tonumber(L,-1); if (IS_INT64_EQUIVALENT(n)) { @@ -372,10 +376,10 @@ static void mp_encode_lua_number(lua_State *L, mp_buf *buf) { } } -static void mp_encode_lua_type(lua_State *L, mp_buf *buf, int level); +void mp_encode_lua_type(lua_State *L, mp_buf *buf, int level); /* Convert a lua table into a message pack list. */ -static void mp_encode_lua_table_as_array(lua_State *L, mp_buf *buf, int level) { +void mp_encode_lua_table_as_array(lua_State *L, mp_buf *buf, int level) { #if LUA_VERSION_NUM < 502 size_t len = lua_objlen(L,-1), j; #else @@ -391,7 +395,7 @@ static void mp_encode_lua_table_as_array(lua_State *L, mp_buf *buf, int level) { } /* Convert a lua table into a message pack key-value map. */ -static void mp_encode_lua_table_as_map(lua_State *L, mp_buf *buf, int level) { +void mp_encode_lua_table_as_map(lua_State *L, mp_buf *buf, int level) { size_t len = 0; /* First step: count keys into table. No other way to do it with the @@ -418,7 +422,7 @@ static void mp_encode_lua_table_as_map(lua_State *L, mp_buf *buf, int level) { /* Returns true if the Lua table on top of the stack is exclusively composed * of keys from numerical keys from 1 up to N, with N being the total number * of elements, without any hole in the middle. */ -static int table_is_an_array(lua_State *L) { +int table_is_an_array(lua_State *L) { int count = 0, max = 0; #if LUA_VERSION_NUM < 503 lua_Number n; @@ -461,14 +465,14 @@ static int table_is_an_array(lua_State *L) { /* If the length operator returns non-zero, that is, there is at least * an object at key '1', we serialize to message pack list. Otherwise * we use a map. */ -static void mp_encode_lua_table(lua_State *L, mp_buf *buf, int level) { +void mp_encode_lua_table(lua_State *L, mp_buf *buf, int level) { if (table_is_an_array(L)) mp_encode_lua_table_as_array(L,buf,level); else mp_encode_lua_table_as_map(L,buf,level); } -static void mp_encode_lua_null(lua_State *L, mp_buf *buf) { +void mp_encode_lua_null(lua_State *L, mp_buf *buf) { unsigned char b[1]; (void)L; @@ -476,7 +480,7 @@ static void mp_encode_lua_null(lua_State *L, mp_buf *buf) { mp_buf_append(buf,b,1); } -static void mp_encode_lua_type(lua_State *L, mp_buf *buf, int level) { +void mp_encode_lua_type(lua_State *L, mp_buf *buf, int level) { int t = lua_type(L,-1); /* Limit the encoding of nested tables to a specified maximum depth, so that @@ -506,7 +510,7 @@ static void mp_encode_lua_type(lua_State *L, mp_buf *buf, int level) { * Packs all arguments as a stream for multiple upacking later. * Returns error if no arguments provided. */ -static int mp_pack(lua_State *L) { +int mp_pack(lua_State *L) { int nargs = lua_gettop(L); int i; mp_buf *buf; @@ -687,6 +691,15 @@ void mp_decode_to_lua_type(lua_State *L, mp_cur *c) { mp_cur_consume(c,9); } break; + case 0xd9: /* raw 8 */ + mp_cur_need(c,2); + { + size_t l = c->p[1]; + mp_cur_need(c,2+l); + lua_pushlstring(L,(char*)c->p+2,l); + mp_cur_consume(c,2+l); + } + break; case 0xda: /* raw 16 */ mp_cur_need(c,3); { @@ -773,7 +786,7 @@ void mp_decode_to_lua_type(lua_State *L, mp_cur *c) { } } -static int mp_unpack_full(lua_State *L, int limit, int offset) { +int mp_unpack_full(lua_State *L, int limit, int offset) { size_t len; const char *s; mp_cur c; @@ -826,18 +839,18 @@ static int mp_unpack_full(lua_State *L, int limit, int offset) { return cnt; } -static int mp_unpack(lua_State *L) { +int mp_unpack(lua_State *L) { return mp_unpack_full(L, 0, 0); } -static int mp_unpack_one(lua_State *L) { +int mp_unpack_one(lua_State *L) { int offset = luaL_optinteger(L, 2, 0); /* Variable pop because offset may not exist */ lua_pop(L, lua_gettop(L)-1); return mp_unpack_full(L, 1, offset); } -static int mp_unpack_limit(lua_State *L) { +int mp_unpack_limit(lua_State *L) { int limit = luaL_checkinteger(L, 2); int offset = luaL_optinteger(L, 3, 0); /* Variable pop because offset may not exist */ @@ -846,7 +859,7 @@ static int mp_unpack_limit(lua_State *L) { return mp_unpack_full(L, limit, offset); } -static int mp_safe(lua_State *L) { +int mp_safe(lua_State *L) { int argc, err, total_results; argc = lua_gettop(L); @@ -869,7 +882,7 @@ static int mp_safe(lua_State *L) { } /* -------------------------------------------------------------------------- */ -static const struct luaL_Reg cmds[] = { +const struct luaL_Reg cmds[] = { {"pack", mp_pack}, {"unpack", mp_unpack}, {"unpack_one", mp_unpack_one}, @@ -877,7 +890,7 @@ static const struct luaL_Reg cmds[] = { {0} }; -static int luaopen_create(lua_State *L) { +int luaopen_create(lua_State *L) { int i; /* Manually construct our module table instead of * relying on _register or _newlib */ diff --git a/msvs/RedisServer.sln b/msvs/RedisServer.sln index 9e07518b214c..fda4656f1208 100644 --- a/msvs/RedisServer.sln +++ b/msvs/RedisServer.sln @@ -33,164 +33,78 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lua", "lua\lua\lua.vcxproj" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Win32_Interop", "..\src\Win32_Interop\Win32_Interop.vcxproj", "{8C07F811-C81C-432C-B334-1AE6FAECF951}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReleasePackagingTool", "ReleasePackagingTool\ReleasePackagingTool.csproj", "{74A69E5D-6540-43CC-9975-20989BF19EB0}" - ProjectSection(ProjectDependencies) = postProject - {46842776-68A5-EC98-6A09-1859BBFC73AA} = {46842776-68A5-EC98-6A09-1859BBFC73AA} - {392BBB91-3934-4A56-AF42-65C5728311E8} = {392BBB91-3934-4A56-AF42-65C5728311E8} - {52193A97-D010-41D6-BF2B-33E8E764E308} = {52193A97-D010-41D6-BF2B-33E8E764E308} - {B00D4BB5-44DE-405E-839C-D16F547006CF} = {B00D4BB5-44DE-405E-839C-D16F547006CF} - {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A} = {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A} - EndProjectSection -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Mixed Platforms = Debug|Mixed Platforms - Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 - Release|Mixed Platforms = Release|Mixed Platforms - Release|Win32 = Release|Win32 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {46842776-68A5-EC98-6A09-1859BBFC73AA}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {46842776-68A5-EC98-6A09-1859BBFC73AA}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {46842776-68A5-EC98-6A09-1859BBFC73AA}.Debug|Win32.ActiveCfg = Debug|Win32 - {46842776-68A5-EC98-6A09-1859BBFC73AA}.Debug|Win32.Build.0 = Debug|Win32 {46842776-68A5-EC98-6A09-1859BBFC73AA}.Debug|x64.ActiveCfg = Debug|x64 {46842776-68A5-EC98-6A09-1859BBFC73AA}.Debug|x64.Build.0 = Debug|x64 {46842776-68A5-EC98-6A09-1859BBFC73AA}.Debug|x86.ActiveCfg = Debug|Win32 {46842776-68A5-EC98-6A09-1859BBFC73AA}.Debug|x86.Build.0 = Debug|Win32 - {46842776-68A5-EC98-6A09-1859BBFC73AA}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {46842776-68A5-EC98-6A09-1859BBFC73AA}.Release|Mixed Platforms.Build.0 = Release|Win32 - {46842776-68A5-EC98-6A09-1859BBFC73AA}.Release|Win32.ActiveCfg = Release|Win32 - {46842776-68A5-EC98-6A09-1859BBFC73AA}.Release|Win32.Build.0 = Release|Win32 {46842776-68A5-EC98-6A09-1859BBFC73AA}.Release|x64.ActiveCfg = Release|x64 {46842776-68A5-EC98-6A09-1859BBFC73AA}.Release|x64.Build.0 = Release|x64 {46842776-68A5-EC98-6A09-1859BBFC73AA}.Release|x86.ActiveCfg = Release|Win32 {46842776-68A5-EC98-6A09-1859BBFC73AA}.Release|x86.Build.0 = Release|Win32 - {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Debug|Win32.ActiveCfg = Debug|Win32 - {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Debug|Win32.Build.0 = Debug|Win32 {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Debug|x64.ActiveCfg = Debug|x64 {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Debug|x64.Build.0 = Debug|x64 {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Debug|x86.ActiveCfg = Debug|Win32 {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Debug|x86.Build.0 = Debug|Win32 - {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Release|Mixed Platforms.Build.0 = Release|Win32 - {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Release|Win32.ActiveCfg = Release|Win32 - {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Release|Win32.Build.0 = Release|Win32 {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Release|x64.ActiveCfg = Release|x64 {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Release|x64.Build.0 = Release|x64 {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Release|x86.ActiveCfg = Release|Win32 {13E85053-54B3-487B-8DDB-3430B1C1B3BF}.Release|x86.Build.0 = Release|Win32 - {B00D4BB5-44DE-405E-839C-D16F547006CF}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {B00D4BB5-44DE-405E-839C-D16F547006CF}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {B00D4BB5-44DE-405E-839C-D16F547006CF}.Debug|Win32.ActiveCfg = Debug|Win32 - {B00D4BB5-44DE-405E-839C-D16F547006CF}.Debug|Win32.Build.0 = Debug|Win32 {B00D4BB5-44DE-405E-839C-D16F547006CF}.Debug|x64.ActiveCfg = Debug|x64 {B00D4BB5-44DE-405E-839C-D16F547006CF}.Debug|x64.Build.0 = Debug|x64 {B00D4BB5-44DE-405E-839C-D16F547006CF}.Debug|x86.ActiveCfg = Debug|Win32 {B00D4BB5-44DE-405E-839C-D16F547006CF}.Debug|x86.Build.0 = Debug|Win32 - {B00D4BB5-44DE-405E-839C-D16F547006CF}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {B00D4BB5-44DE-405E-839C-D16F547006CF}.Release|Mixed Platforms.Build.0 = Release|Win32 - {B00D4BB5-44DE-405E-839C-D16F547006CF}.Release|Win32.ActiveCfg = Release|Win32 - {B00D4BB5-44DE-405E-839C-D16F547006CF}.Release|Win32.Build.0 = Release|Win32 {B00D4BB5-44DE-405E-839C-D16F547006CF}.Release|x64.ActiveCfg = Release|x64 {B00D4BB5-44DE-405E-839C-D16F547006CF}.Release|x64.Build.0 = Release|x64 {B00D4BB5-44DE-405E-839C-D16F547006CF}.Release|x86.ActiveCfg = Release|Win32 {B00D4BB5-44DE-405E-839C-D16F547006CF}.Release|x86.Build.0 = Release|Win32 - {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Debug|Win32.ActiveCfg = Debug|Win32 - {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Debug|Win32.Build.0 = Debug|Win32 {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Debug|x64.ActiveCfg = Debug|x64 {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Debug|x64.Build.0 = Debug|x64 {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Debug|x86.ActiveCfg = Debug|Win32 {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Debug|x86.Build.0 = Debug|Win32 - {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Release|Mixed Platforms.Build.0 = Release|Win32 - {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Release|Win32.ActiveCfg = Release|Win32 - {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Release|Win32.Build.0 = Release|Win32 {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Release|x64.ActiveCfg = Release|x64 {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Release|x64.Build.0 = Release|x64 {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Release|x86.ActiveCfg = Release|Win32 {A65C2CD6-72A3-441A-AEA3-D754BEA9A86A}.Release|x86.Build.0 = Release|Win32 - {52193A97-D010-41D6-BF2B-33E8E764E308}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {52193A97-D010-41D6-BF2B-33E8E764E308}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {52193A97-D010-41D6-BF2B-33E8E764E308}.Debug|Win32.ActiveCfg = Debug|Win32 - {52193A97-D010-41D6-BF2B-33E8E764E308}.Debug|Win32.Build.0 = Debug|Win32 {52193A97-D010-41D6-BF2B-33E8E764E308}.Debug|x64.ActiveCfg = Debug|x64 {52193A97-D010-41D6-BF2B-33E8E764E308}.Debug|x64.Build.0 = Debug|x64 {52193A97-D010-41D6-BF2B-33E8E764E308}.Debug|x86.ActiveCfg = Debug|Win32 {52193A97-D010-41D6-BF2B-33E8E764E308}.Debug|x86.Build.0 = Debug|Win32 - {52193A97-D010-41D6-BF2B-33E8E764E308}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {52193A97-D010-41D6-BF2B-33E8E764E308}.Release|Mixed Platforms.Build.0 = Release|Win32 - {52193A97-D010-41D6-BF2B-33E8E764E308}.Release|Win32.ActiveCfg = Release|Win32 - {52193A97-D010-41D6-BF2B-33E8E764E308}.Release|Win32.Build.0 = Release|Win32 {52193A97-D010-41D6-BF2B-33E8E764E308}.Release|x64.ActiveCfg = Release|x64 {52193A97-D010-41D6-BF2B-33E8E764E308}.Release|x64.Build.0 = Release|x64 {52193A97-D010-41D6-BF2B-33E8E764E308}.Release|x86.ActiveCfg = Release|Win32 {52193A97-D010-41D6-BF2B-33E8E764E308}.Release|x86.Build.0 = Release|Win32 - {392BBB91-3934-4A56-AF42-65C5728311E8}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {392BBB91-3934-4A56-AF42-65C5728311E8}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {392BBB91-3934-4A56-AF42-65C5728311E8}.Debug|Win32.ActiveCfg = Debug|Win32 - {392BBB91-3934-4A56-AF42-65C5728311E8}.Debug|Win32.Build.0 = Debug|Win32 {392BBB91-3934-4A56-AF42-65C5728311E8}.Debug|x64.ActiveCfg = Debug|x64 {392BBB91-3934-4A56-AF42-65C5728311E8}.Debug|x64.Build.0 = Debug|x64 {392BBB91-3934-4A56-AF42-65C5728311E8}.Debug|x86.ActiveCfg = Debug|Win32 {392BBB91-3934-4A56-AF42-65C5728311E8}.Debug|x86.Build.0 = Debug|Win32 - {392BBB91-3934-4A56-AF42-65C5728311E8}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {392BBB91-3934-4A56-AF42-65C5728311E8}.Release|Mixed Platforms.Build.0 = Release|Win32 - {392BBB91-3934-4A56-AF42-65C5728311E8}.Release|Win32.ActiveCfg = Release|Win32 - {392BBB91-3934-4A56-AF42-65C5728311E8}.Release|Win32.Build.0 = Release|Win32 {392BBB91-3934-4A56-AF42-65C5728311E8}.Release|x64.ActiveCfg = Release|x64 {392BBB91-3934-4A56-AF42-65C5728311E8}.Release|x64.Build.0 = Release|x64 {392BBB91-3934-4A56-AF42-65C5728311E8}.Release|x86.ActiveCfg = Release|Win32 {392BBB91-3934-4A56-AF42-65C5728311E8}.Release|x86.Build.0 = Release|Win32 - {170B0909-5F75-467F-9501-C99DEC16C6DC}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {170B0909-5F75-467F-9501-C99DEC16C6DC}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {170B0909-5F75-467F-9501-C99DEC16C6DC}.Debug|Win32.ActiveCfg = Debug|Win32 - {170B0909-5F75-467F-9501-C99DEC16C6DC}.Debug|Win32.Build.0 = Debug|Win32 {170B0909-5F75-467F-9501-C99DEC16C6DC}.Debug|x64.ActiveCfg = Debug|x64 {170B0909-5F75-467F-9501-C99DEC16C6DC}.Debug|x64.Build.0 = Debug|x64 {170B0909-5F75-467F-9501-C99DEC16C6DC}.Debug|x86.ActiveCfg = Debug|Win32 {170B0909-5F75-467F-9501-C99DEC16C6DC}.Debug|x86.Build.0 = Debug|Win32 - {170B0909-5F75-467F-9501-C99DEC16C6DC}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {170B0909-5F75-467F-9501-C99DEC16C6DC}.Release|Mixed Platforms.Build.0 = Release|Win32 - {170B0909-5F75-467F-9501-C99DEC16C6DC}.Release|Win32.ActiveCfg = Release|Win32 - {170B0909-5F75-467F-9501-C99DEC16C6DC}.Release|Win32.Build.0 = Release|Win32 {170B0909-5F75-467F-9501-C99DEC16C6DC}.Release|x64.ActiveCfg = Release|x64 {170B0909-5F75-467F-9501-C99DEC16C6DC}.Release|x64.Build.0 = Release|x64 {170B0909-5F75-467F-9501-C99DEC16C6DC}.Release|x86.ActiveCfg = Release|Win32 {170B0909-5F75-467F-9501-C99DEC16C6DC}.Release|x86.Build.0 = Release|Win32 - {8C07F811-C81C-432C-B334-1AE6FAECF951}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 - {8C07F811-C81C-432C-B334-1AE6FAECF951}.Debug|Mixed Platforms.Build.0 = Debug|Win32 - {8C07F811-C81C-432C-B334-1AE6FAECF951}.Debug|Win32.ActiveCfg = Debug|Win32 - {8C07F811-C81C-432C-B334-1AE6FAECF951}.Debug|Win32.Build.0 = Debug|Win32 {8C07F811-C81C-432C-B334-1AE6FAECF951}.Debug|x64.ActiveCfg = Debug|x64 {8C07F811-C81C-432C-B334-1AE6FAECF951}.Debug|x64.Build.0 = Debug|x64 {8C07F811-C81C-432C-B334-1AE6FAECF951}.Debug|x86.ActiveCfg = Debug|Win32 {8C07F811-C81C-432C-B334-1AE6FAECF951}.Debug|x86.Build.0 = Debug|Win32 - {8C07F811-C81C-432C-B334-1AE6FAECF951}.Release|Mixed Platforms.ActiveCfg = Release|Win32 - {8C07F811-C81C-432C-B334-1AE6FAECF951}.Release|Mixed Platforms.Build.0 = Release|Win32 - {8C07F811-C81C-432C-B334-1AE6FAECF951}.Release|Win32.ActiveCfg = Release|Win32 - {8C07F811-C81C-432C-B334-1AE6FAECF951}.Release|Win32.Build.0 = Release|Win32 {8C07F811-C81C-432C-B334-1AE6FAECF951}.Release|x64.ActiveCfg = Release|x64 {8C07F811-C81C-432C-B334-1AE6FAECF951}.Release|x64.Build.0 = Release|x64 {8C07F811-C81C-432C-B334-1AE6FAECF951}.Release|x86.ActiveCfg = Release|Win32 {8C07F811-C81C-432C-B334-1AE6FAECF951}.Release|x86.Build.0 = Release|Win32 - {74A69E5D-6540-43CC-9975-20989BF19EB0}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 - {74A69E5D-6540-43CC-9975-20989BF19EB0}.Debug|Win32.ActiveCfg = Debug|x64 - {74A69E5D-6540-43CC-9975-20989BF19EB0}.Debug|x64.ActiveCfg = Release|x64 - {74A69E5D-6540-43CC-9975-20989BF19EB0}.Debug|x86.ActiveCfg = Debug|x64 - {74A69E5D-6540-43CC-9975-20989BF19EB0}.Release|Mixed Platforms.ActiveCfg = Release|x64 - {74A69E5D-6540-43CC-9975-20989BF19EB0}.Release|Mixed Platforms.Build.0 = Release|x64 - {74A69E5D-6540-43CC-9975-20989BF19EB0}.Release|Win32.ActiveCfg = Release|x64 - {74A69E5D-6540-43CC-9975-20989BF19EB0}.Release|x64.ActiveCfg = Release|x64 - {74A69E5D-6540-43CC-9975-20989BF19EB0}.Release|x86.ActiveCfg = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/msvs/ReleasePackagingTool/Program.cs b/msvs/ReleasePackagingTool/Program.cs index dd7d1789b6f8..c00021b34ec8 100644 --- a/msvs/ReleasePackagingTool/Program.cs +++ b/msvs/ReleasePackagingTool/Program.cs @@ -28,16 +28,15 @@ static void Main(string[] args) string version; version = p.GetRedisVersion(); - p.UpdateReleaseNotes(version); p.UpdateNuSpecFiles(version); p.BuildReleasePackage(version); - p.DocxToMd(); + Console.Write("Release packaging complete."); Environment.ExitCode = 0; } catch(Exception ex) { - Console.WriteLine("Error. Failed to finish release packaging. \n" + ex.ToString()); + Console.WriteLine("Error. Failed to finish release packaging.\n" + ex.ToString()); Environment.ExitCode = -1; } } @@ -51,70 +50,6 @@ string GetRedisVersion() return line.Substring(start + 1, last - start - 1); } - void DocxToMd() - { - // locate converter (pandoc v1.13.0+) - string pandocToolPath = Path.Combine(rootPath, @"msvs\tools\pandoc\pandoc.exe"); - if (File.Exists(pandocToolPath)) - { - var files = Directory.EnumerateFiles(Path.Combine(rootPath, @"msvs\setups\documentation"), "*.docx"); - foreach (string sourceFile in files) - { - string fileName = Path.GetFileName(sourceFile); - string destFile = Path.ChangeExtension(Path.Combine(rootPath, fileName), "md"); - System.Diagnostics.Process p = new Process(); - p.StartInfo.FileName = pandocToolPath; - p.StartInfo.UseShellExecute = false; - p.StartInfo.Arguments = string.Format( - "-f {0} -t {1} -o \"{2}\" \"{3}\"", - "docx", - "markdown_github", - destFile, - sourceFile); - p.Start(); - p.WaitForExit(); - if (p.ExitCode != 0) - { - Console.WriteLine("conversion of'{0}' to '{1}' failed.", sourceFile, destFile); - } - } - } - else - { - Console.WriteLine("pandoc tool not found. docx-->md conversion will not take place."); - } - } - - void UpdateReleaseNotes(string redisVersion) - { - string releaseNotesPath = Path.Combine(rootPath, @"msvs\setups\documentation\Redis on Windows Release Notes.docx"); - string templatePath = Path.Combine(rootPath, @"msvs\setups\documentation\templates\Redis Release Notes Template.docx"); - - ForceFileErase(releaseNotesPath); - File.Copy(templatePath, releaseNotesPath); - - var archive = ZipFile.Open(releaseNotesPath, ZipArchiveMode.Update); - - string docuemntContent = @"word/document.xml"; - ZipArchiveEntry entry = archive.GetEntry(docuemntContent); - string updatedContent; - using (TextReader tr = new StreamReader(entry.Open())) - { - string documentContent = tr.ReadToEnd(); - updatedContent = documentContent.Replace(versionReplacementText, redisVersion); - } - entry.Delete(); - archive.Dispose(); // forces the file to be written to disk with the documentContent entry deleted - - archive = System.IO.Compression.ZipFile.Open(releaseNotesPath, ZipArchiveMode.Update); - ZipArchiveEntry updatedEntry = archive.CreateEntry(docuemntContent, CompressionLevel.Optimal); - using (TextWriter tw = new StreamWriter(updatedEntry.Open())) - { - tw.Write(updatedContent); - } - archive.Dispose(); // rewrites the file with the updated content - } - void ForceFileErase(string file) { if (File.Exists(file)) @@ -143,17 +78,23 @@ void CreateTextFileFromTemplate(string templatePath, string documentPath, string void UpdateNuSpecFiles(string redisVersion) { - string chocTemplate = Path.Combine(rootPath, @"msvs\setups\chocolatey\template\Redis.nuspec.template"); - string chocDocument = Path.Combine(rootPath, @"msvs\setups\chocolatey\Redis.nuspec"); + string chocTemplate = Path.Combine(rootPath, @"msvs\setups\chocolatey\template\redis.nuspec.template"); + string chocDocument = Path.Combine(rootPath, @"msvs\setups\chocolatey\redis.nuspec"); CreateTextFileFromTemplate(chocTemplate, chocDocument, versionReplacementText, redisVersion); - string nugetTemplate = Path.Combine(rootPath, @"msvs\setups\nuget\template\Redis.nuspec.template"); - string nugetDocument = Path.Combine(rootPath, @"msvs\setups\nuget\Redis.nuspec"); + string nugetTemplate = Path.Combine(rootPath, @"msvs\setups\nuget\template\redis.nuspec.template"); + string nugetDocument = Path.Combine(rootPath, @"msvs\setups\nuget\redis.nuspec"); CreateTextFileFromTemplate(nugetTemplate, nugetDocument, versionReplacementText, redisVersion); } void BuildReleasePackage(string version) { + string releasePackageDir = Path.Combine(rootPath, @"bin\Release\"); + if (Directory.Exists(releasePackageDir) == false) + { + Directory.CreateDirectory(releasePackageDir); + } + string releasePackagePath = Path.Combine(rootPath, @"bin\Release\redis-" + version + ".zip"); ForceFileErase(releasePackagePath); @@ -164,7 +105,9 @@ void BuildReleasePackage(string version) "redis-check-aof.exe", "redis-check-dump.exe", "redis-cli.exe", - "redis-server.exe" + "redis-server.exe", + "redis-server.pdb", + "EventLog.dll" }; string documentsRoot = Path.Combine(rootPath, @"msvs\setups\documentation"); List docuementNames = new List() @@ -172,7 +115,8 @@ void BuildReleasePackage(string version) "Redis on Windows.docx", "Redis on Windows Release Notes.docx", "Windows Service Documentation.docx", - "redis.windows.conf" + "redis.windows.conf", + "redis.windows-service.conf" }; using (ZipArchive archive = ZipFile.Open(releasePackagePath, ZipArchiveMode.Create)) diff --git a/msvs/ReleasePackagingTool/ReleasePackagingTool.csproj b/msvs/ReleasePackagingTool/ReleasePackagingTool.csproj index 0302b6db43ce..8d42cbe3e1ac 100644 --- a/msvs/ReleasePackagingTool/ReleasePackagingTool.csproj +++ b/msvs/ReleasePackagingTool/ReleasePackagingTool.csproj @@ -11,6 +11,7 @@ ReleasePackagingTool v4.5 512 + false publish\ true Disk @@ -23,7 +24,6 @@ true 0 1.0.0.%2a - false false true @@ -51,6 +51,9 @@ Always + + ReleasePackagingTool.Program + @@ -88,7 +91,8 @@ - $(TargetPath) + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvs/msi/RedisMsi/Components/WindowsServiceComponents.wxs b/msvs/msi/RedisMsi/Components/WindowsServiceComponents.wxs index df936424e405..98b9727c52f8 100644 --- a/msvs/msi/RedisMsi/Components/WindowsServiceComponents.wxs +++ b/msvs/msi/RedisMsi/Components/WindowsServiceComponents.wxs @@ -40,7 +40,7 @@ The following component creates the firewall exception. --> - + 1]]> - - - - - - - - - \ No newline at end of file diff --git a/msvs/msi/RedisMsi/CustomActions.wxs b/msvs/msi/RedisMsi/CustomActions.wxs new file mode 100644 index 000000000000..6706a4398ff2 --- /dev/null +++ b/msvs/msi/RedisMsi/CustomActions.wxs @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/msvs/msi/RedisMsi/Dialogs/FirewallDialog.wxs b/msvs/msi/RedisMsi/Dialogs/FirewallDialog.wxs index 811fba3a7152..de71a8ca05f3 100644 --- a/msvs/msi/RedisMsi/Dialogs/FirewallDialog.wxs +++ b/msvs/msi/RedisMsi/Dialogs/FirewallDialog.wxs @@ -2,6 +2,8 @@ + + @@ -18,7 +20,12 @@ - + + + + diff --git a/msvs/msi/RedisMsi/License.rtf b/msvs/msi/RedisMsi/License.rtf index 9e56c04795e5..ae5237cc2479 100644 Binary files a/msvs/msi/RedisMsi/License.rtf and b/msvs/msi/RedisMsi/License.rtf differ diff --git a/msvs/msi/RedisMsi/Product.wxs b/msvs/msi/RedisMsi/Product.wxs index 20709288e320..b9fa14e61b06 100644 --- a/msvs/msi/RedisMsi/Product.wxs +++ b/msvs/msi/RedisMsi/Product.wxs @@ -10,10 +10,10 @@ msiexec /i Redis-[version].msi set port and turn off firewall exception: - msiexec /i Redis-[version].msi PORT=1234 FIREWALL_ON="" + msiexec /i Redis-[version].msi PORT=1234 ADD_FIREWALL_RULE="" set port and turn on firewall exception: - msiexec /i Redis-[version].msi PORT=1234 FIREWALL_ON=1 + msiexec /i Redis-[version].msi PORT=1234 ADD_FIREWALL_RULE=1 --> @@ -21,7 +21,7 @@ - + + + + + + diff --git a/msvs/msi/RedisMsi/RedisMsi.wixproj b/msvs/msi/RedisMsi/RedisMsi.wixproj index b5cacacf176c..05a6acc7b560 100644 --- a/msvs/msi/RedisMsi/RedisMsi.wixproj +++ b/msvs/msi/RedisMsi/RedisMsi.wixproj @@ -39,7 +39,9 @@ + + @@ -56,7 +58,7 @@ - ..\..\..\..\Program Files (x86)\WiX Toolset v3.9\bin\WixUIExtension.dll + $(WixExtDir)\WixUIExtension.dll WixUIExtension diff --git a/msvs/setups/CreatePackages.ps1 b/msvs/setups/CreatePackages.ps1 index 9baab1addc7b..479eda9f33dc 100644 --- a/msvs/setups/CreatePackages.ps1 +++ b/msvs/setups/CreatePackages.ps1 @@ -1,25 +1,36 @@ -$CurDir = split-path -parent $MyInvocation.MyCommand.Definition +$ErrorActionPreference = "Stop" -$ChocolateyDir = $CurDir + "\chocolatey" -$NugetDir = $CurDir + "\nuget" -$PackagesDir = $CurDir + "\packages" +$CurDir = split-path -parent $MyInvocation.MyCommand.Definition +$PackagesDir = $CurDir + "\packages" +$ChocolateySrcDir = $CurDir + "\chocolatey" +$ChocolateyDestDir = $PackagesDir + "\chocolatey" +$NugetSrcDir = $CurDir + "\nuget" +$NugetDestDir = $PackagesDir + "\nuget" If (Test-Path $PackagesDir){ Remove-Item $PackagesDir -recurse | Out-Null } -New-Item $PackagesDir -type directory | Out-Null -New-Item ($PackagesDir+"\Chocolatey") -type directory | Out-Null -New-Item ($PackagesDir+"\NuGet") -type directory | Out-Null +New-Item $PackagesDir -type directory | Out-Null +New-Item $ChocolateyDestDir -type directory | Out-Null +New-Item $NugetDestDir -type directory | Out-Null -Set-Location $ChocolateyDir +Set-Location $ChocolateySrcDir invoke-expression "chocolatey pack Redis.nuspec" -Copy-Item *.nupkg ..\packages\Chocolatey +if ($LASTEXITCODE -eq 0) { + Copy-Item *.nupkg $ChocolateyDestDir + Write-Host "Chocolatey package copied to the destination folder." -foregroundcolor black -backgroundcolor green +} else { + Write-Host "FAILED to create the Chocolatey package." -foregroundcolor white -backgroundcolor red +} -Set-Location $NugetDir -invoke-expression "NuGet Pack Redis.nuspec" -Copy-Item *.nupkg ..\packages\NuGet +Set-Location $NugetSrcDir +invoke-expression "nuget pack Redis.nuspec" +if ($LASTEXITCODE -eq 0) { + Copy-Item *.nupkg $NugetDestDir + Write-Host "NuGet package copied to the destination folder." -foregroundcolor black -backgroundcolor green +} else { + Write-Host "FAILED to create the NuGet package." -foregroundcolor white -backgroundcolor red +} +Write-Host "Run PushPackages to push the packages." -foregroundcolor red -backgroundcolor yellow Set-Location $CurDir - -Write-Host "The .nupkg files are in the 'packages' directory." -foregroundcolor black -backgroundcolor green -Write-Host "Run PushPackages to push them." -foregroundcolor red -backgroundcolor yellow diff --git a/msvs/setups/PullBinaries.ps1 b/msvs/setups/PullBinaries.ps1 index c65b8c51a43f..eb0464d99b62 100644 --- a/msvs/setups/PullBinaries.ps1 +++ b/msvs/setups/PullBinaries.ps1 @@ -1,17 +1,32 @@ -[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null +param ( + [string] $Version = $(throw 'Redis version to download is required') +) -$CurDir = split-path -parent $MyInvocation.MyCommand.Definition +$ErrorActionPreference = "Stop" +[Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null -$SourceZip = [System.IO.Path]::Combine($CurDir, "..\..\bin\Release\redis-2.8.16.zip" ) -$Destination = [System.IO.Path]::Combine($CurDir, "signed_binaries" ) +$ZipFilename = "redis-x64-" + $Version + ".zip" +$CurDir = split-path -parent $MyInvocation.MyCommand.Definition +$SourceZip = [System.IO.Path]::Combine($CurDir, $ZipFilename ) +$DestinationDir = [System.IO.Path]::Combine($CurDir, "signed_binaries" ) +$GithubUrl = "https://github.com/MSOpenTech/redis/releases/download/win-" + $Version + "/" + $ZipFilename -[System.IO.Directory]::CreateDirectory($Destination) | Out-Null +[System.IO.File]::Delete($SourceZip) +[System.IO.Directory]::CreateDirectory($DestinationDir) | Out-Null -ForEach( $file in [System.IO.Directory]::EnumerateFiles($Destination) ) { +ForEach( $file in [System.IO.Directory]::EnumerateFiles($DestinationDir) ) { [System.IO.File]::Delete($file) } -[System.IO.Compression.ZipFile]::ExtractToDirectory($SourceZip,$Destination) +Write-Host "Downloading zip file from $GithubUrl" +(New-Object Net.WebClient).DownloadFile($GithubUrl, $SourceZip); +Write-Host "Download complete." -foregroundcolor black -backgroundcolor green + +Write-Host "Extracting files to $DestinationDir" +[System.IO.Compression.ZipFile]::ExtractToDirectory($SourceZip,$DestinationDir) +Write-Host "Extraction complete." -foregroundcolor black -backgroundcolor green + +# Clean up +[System.IO.File]::Delete($SourceZip) -Write-Host "Binaries copied from $SourceZip to $Destination" -foregroundcolor black -backgroundcolor green -Write-Host "Sign these and then run CreatePackages.ps1" -foregroundcolor red -backgroundcolor yellow +Write-Host "Sign the binaries and then run CreatePackages.ps1" -foregroundcolor red -backgroundcolor yellow diff --git a/msvs/setups/PushPackages.ps1 b/msvs/setups/PushPackages.ps1 index e61f8f546a37..d6a290104246 100644 --- a/msvs/setups/PushPackages.ps1 +++ b/msvs/setups/PushPackages.ps1 @@ -2,6 +2,8 @@ param ( [string] $Version = $(throw 'Redis version to push is required') ) +$ErrorActionPreference = "Stop" + Write-Host "Ensure that the api keys have been set for chocolatey and nuget" -foregroundcolor red -backgroundcolor yellow Write-Host " NuGet SetApiKey -source http://chocolatey.org/" -foregroundcolor red -backgroundcolor yellow Write-Host " NuGet SetApiKey " -foregroundcolor red -backgroundcolor yellow @@ -9,17 +11,26 @@ Write-Host " NuGet SetApiKey " -foregroundcolor red -backgroundc $CurDir = split-path -parent $MyInvocation.MyCommand.Definition $PackagesDir = $CurDir + "\packages" -$ChocolateyDir = $PackagesDir + "\Chocolatey" -$NugetDir = $PackagesDir + "\Nuget" +$ChocolateyDir = $PackagesDir + "\chocolatey" +$NugetDir = $PackagesDir + "\nuget" Set-Location $ChocolateyDir $ChocolateyCommand = "chocolatey push Redis-64." + $Version + ".nupkg" invoke-expression $ChocolateyCommand +if ($LASTEXITCODE -eq 0) { + Write-Host "Chocolatey package pushed successfully." -foregroundcolor black -backgroundcolor green +} else { + Write-Host "FAILED to push the Chocolatey package." -foregroundcolor white -backgroundcolor red +} Set-Location $NugetDir $NugetCommand = "NuGet push Redis-64." + $Version + ".nupkg" invoke-expression $NugetCommand +if ($LASTEXITCODE -eq 0) { + Write-Host "NuGet package pushed successfully" -foregroundcolor black -backgroundcolor green +} else { + Write-Host "FAILED to push the NuGet package." -foregroundcolor white -backgroundcolor red +} Set-Location $CurDir -Write-Host "The .nupkg files have been pushed!" -foregroundcolor black -backgroundcolor green diff --git a/msvs/setups/chocolatey/Redis.nuspec b/msvs/setups/chocolatey/Redis.nuspec index 40860f5e8900..f4659f5f4a76 100644 --- a/msvs/setups/chocolatey/Redis.nuspec +++ b/msvs/setups/chocolatey/Redis.nuspec @@ -2,22 +2,21 @@ redis-64 - redis-64 - 2.8.20 - Jonathan Pickett + Redis 64 + 2.8.21 + Alexis Campailla, Enrico Giordani, Jonathan Pickett Microsoft Open Technologies, Inc. Redis is a very popular open-source, networked, in-memory, key-value data store known for high performance, flexibility, a rich set of data structures, and a simple straightforward API. - A production-ready Windows port of Redis, including 64-bit support, Chocolatey support, and much more. + Redis on Windows 64-bit. https://msopentech.com/opentech-projects/redis/ Redis nosql cache Copyright Microsoft Open Technologies, Inc. https://github.com/MSOpenTech/redis/blob/2.8/license.txt false http://redis.io/images/redis.png - Includes the changes from Redis 2.8.12 -> 2.8.20. Please see the release notes for the UNIX 2.8 branch to understand how this impacts Redis functionality. + https://raw.githubusercontent.com/MSOpenTech/redis/2.8/Redis%20on%20Windows%20Release%20Notes.md - diff --git a/msvs/setups/chocolatey/template/Redis.nuspec.template b/msvs/setups/chocolatey/template/Redis.nuspec.template index c44066ed0105..3c3f964c473f 100644 --- a/msvs/setups/chocolatey/template/Redis.nuspec.template +++ b/msvs/setups/chocolatey/template/Redis.nuspec.template @@ -2,22 +2,21 @@ redis-64 - redis-64 + Redis 64 CurrentRedisVersion - Jonathan Pickett + Alexis Campailla, Enrico Giordani, Jonathan Pickett Microsoft Open Technologies, Inc. Redis is a very popular open-source, networked, in-memory, key-value data store known for high performance, flexibility, a rich set of data structures, and a simple straightforward API. - A production-ready Windows port of Redis, including 64-bit support, Chocolatey support, and much more. + Redis on Windows 64-bit. https://msopentech.com/opentech-projects/redis/ Redis nosql cache Copyright Microsoft Open Technologies, Inc. https://github.com/MSOpenTech/redis/blob/2.8/license.txt false http://redis.io/images/redis.png - Includes the changes from Redis 2.8.12 -> CurrentRedisVersion. Please see the release notes for the UNIX 2.8 branch to understand how this impacts Redis functionality. + https://raw.githubusercontent.com/MSOpenTech/redis/2.8/Redis%20on%20Windows%20Release%20Notes.md - diff --git a/msvs/setups/documentation/Redis on Windows Release Notes.docx b/msvs/setups/documentation/Redis on Windows Release Notes.docx index 76df8288ad46..54c67e044424 100644 Binary files a/msvs/setups/documentation/Redis on Windows Release Notes.docx and b/msvs/setups/documentation/Redis on Windows Release Notes.docx differ diff --git a/msvs/setups/documentation/Windows Service Documentation.docx b/msvs/setups/documentation/Windows Service Documentation.docx index 78ec939a4d9d..9e333d68d08d 100644 Binary files a/msvs/setups/documentation/Windows Service Documentation.docx and b/msvs/setups/documentation/Windows Service Documentation.docx differ diff --git a/msvs/setups/documentation/redis.windows-service.conf b/msvs/setups/documentation/redis.windows-service.conf index 065480db7dae..4510bfb58355 100644 --- a/msvs/setups/documentation/redis.windows-service.conf +++ b/msvs/setups/documentation/redis.windows-service.conf @@ -497,6 +497,9 @@ slave-priority 100 # limit for maxmemory so that there is some free RAM on the system for slave # output buffers (but this is not needed if the policy is 'noeviction'). # +# WARNING: not setting maxmemory will cause Redis to terminate with an +# out-of-memory exception if the maxheap limit is reached. +# # maxmemory # MAXMEMORY POLICY: how Redis will select what to remove when maxmemory diff --git a/msvs/setups/documentation/redis.windows.conf b/msvs/setups/documentation/redis.windows.conf index bc3fd35c3a4c..4e85f8955a58 100644 --- a/msvs/setups/documentation/redis.windows.conf +++ b/msvs/setups/documentation/redis.windows.conf @@ -497,6 +497,9 @@ slave-priority 100 # limit for maxmemory so that there is some free RAM on the system for slave # output buffers (but this is not needed if the policy is 'noeviction'). # +# WARNING: not setting maxmemory will cause Redis to terminate with an +# out-of-memory exception if the maxheap limit is reached. +# # maxmemory # MAXMEMORY POLICY: how Redis will select what to remove when maxmemory diff --git a/msvs/setups/documentation/templates/Redis Release Notes Template.docx b/msvs/setups/documentation/templates/Redis Release Notes Template.docx deleted file mode 100644 index 7136d26c3919..000000000000 Binary files a/msvs/setups/documentation/templates/Redis Release Notes Template.docx and /dev/null differ diff --git a/msvs/setups/nuget/Redis.nuspec b/msvs/setups/nuget/Redis.nuspec index 40860f5e8900..10a596088910 100644 --- a/msvs/setups/nuget/Redis.nuspec +++ b/msvs/setups/nuget/Redis.nuspec @@ -2,22 +2,24 @@ redis-64 - redis-64 - 2.8.20 - Jonathan Pickett + Redis-64 + 2.8.21 + Alexis Campailla, Enrico Giordani, Jonathan Pickett Microsoft Open Technologies, Inc. Redis is a very popular open-source, networked, in-memory, key-value data store known for high performance, flexibility, a rich set of data structures, and a simple straightforward API. - A production-ready Windows port of Redis, including 64-bit support, Chocolatey support, and much more. + Redis on Windows 64-bit. https://msopentech.com/opentech-projects/redis/ Redis nosql cache Copyright Microsoft Open Technologies, Inc. https://github.com/MSOpenTech/redis/blob/2.8/license.txt false http://redis.io/images/redis.png - Includes the changes from Redis 2.8.12 -> 2.8.20. Please see the release notes for the UNIX 2.8 branch to understand how this impacts Redis functionality. + https://raw.githubusercontent.com/MSOpenTech/redis/2.8/Redis%20on%20Windows%20Release%20Notes.md - - + + + + diff --git a/msvs/setups/nuget/template/Redis.nuspec.template b/msvs/setups/nuget/template/Redis.nuspec.template index c44066ed0105..cc224dc1475c 100644 --- a/msvs/setups/nuget/template/Redis.nuspec.template +++ b/msvs/setups/nuget/template/Redis.nuspec.template @@ -2,22 +2,24 @@ redis-64 - redis-64 + Redis-64 CurrentRedisVersion - Jonathan Pickett + Alexis Campailla, Enrico Giordani, Jonathan Pickett Microsoft Open Technologies, Inc. Redis is a very popular open-source, networked, in-memory, key-value data store known for high performance, flexibility, a rich set of data structures, and a simple straightforward API. - A production-ready Windows port of Redis, including 64-bit support, Chocolatey support, and much more. + Redis on Windows 64-bit. https://msopentech.com/opentech-projects/redis/ Redis nosql cache Copyright Microsoft Open Technologies, Inc. https://github.com/MSOpenTech/redis/blob/2.8/license.txt false http://redis.io/images/redis.png - Includes the changes from Redis 2.8.12 -> CurrentRedisVersion. Please see the release notes for the UNIX 2.8 branch to understand how this impacts Redis functionality. + https://raw.githubusercontent.com/MSOpenTech/redis/2.8/Redis%20on%20Windows%20Release%20Notes.md - - + + + + diff --git a/src/Win32_Interop/Win32_CommandLine.cpp b/src/Win32_Interop/Win32_CommandLine.cpp index a8aeb1b28849..7b37fedd1a46 100644 --- a/src/Win32_Interop/Win32_CommandLine.cpp +++ b/src/Win32_Interop/Win32_CommandLine.cpp @@ -563,7 +563,8 @@ vector incompatibleNoPersistenceCommands{ "no_append_fsync_on_rewrite", "auto_aof_rewrite_percentage", "auto_aof_rewrite_on_size", - "aof_rewrite_incremental_fsync" + "aof_rewrite_incremental_fsync", + "save" }; void ValidateCommandlineCombinations() { @@ -595,41 +596,53 @@ void ParseCommandLineArguments(int argc, char** argv) { string argument = string(argv[n]).substr(2, argument.length() - 2); transform(argument.begin(), argument.end(), argument.begin(), ::tolower); - if (g_redisArgMap.find(argument) == g_redisArgMap.end()) { - stringstream err; - err << "unknown argument: " << argument; - throw invalid_argument(err.str()); - } - - vector params; - if (argument == cSentinel) { - try { - vector sentinelSubCommands = g_redisArgMap[argument]->Extract(n, argc, argv); - for (auto p : sentinelSubCommands) { - params.push_back(p); - } - } catch (invalid_argument iaerr) { - // if no subcommands could be mapped, then assume this is the parameterless --sentinel command line only argument + // Some -- arguments are passed directly to redis.c::main() + if (find(cRedisArgsForMainC.begin(), cRedisArgsForMainC.end(), argument) != cRedisArgsForMainC.end()) { + if (strcasecmp(argument.c_str(), "test-memory") == 0) { + // The test-memory argument is followed by a integer value + n++; } - } else if (argument == cServiceRun ) { - // When the service starts the current directory is %systemdir%. This needs to be changed to the - // directory the executable is in so that the .conf file can be loaded. - char szFilePath[MAX_PATH]; - if (GetModuleFileNameA(NULL, szFilePath, MAX_PATH) == 0) { - throw std::system_error(GetLastError(), system_category(), "ParseCommandLineArguments: GetModuleFileName failed"); + } else { + // -- arguments processed before calling redis.c::main() + if (g_redisArgMap.find(argument) == g_redisArgMap.end()) { + stringstream err; + err << "unknown argument: " << argument; + throw invalid_argument(err.str()); } - string currentDir = szFilePath; - auto pos = currentDir.rfind("\\"); - currentDir.erase(pos); - if (FALSE == SetCurrentDirectoryA(currentDir.c_str())) { - throw std::system_error(GetLastError(), system_category(), "SetCurrentDirectory failed"); + vector params; + if (argument == cSentinel) { + try { + vector sentinelSubCommands = g_redisArgMap[argument]->Extract(n, argc, argv); + for (auto p : sentinelSubCommands) { + params.push_back(p); + } + } + catch (invalid_argument iaerr) { + // if no subcommands could be mapped, then assume this is the parameterless --sentinel command line only argument + } + } else if (argument == cServiceRun) { + // When the service starts the current directory is %systemdir%. This needs to be changed to the + // directory the executable is in so that the .conf file can be loaded. + char szFilePath[MAX_PATH]; + if (GetModuleFileNameA(NULL, szFilePath, MAX_PATH) == 0) { + throw std::system_error(GetLastError(), system_category(), "ParseCommandLineArguments: GetModuleFileName failed"); + } + string currentDir = szFilePath; + auto pos = currentDir.rfind("\\"); + currentDir.erase(pos); + + if (FALSE == SetCurrentDirectoryA(currentDir.c_str())) { + throw std::system_error(GetLastError(), system_category(), "SetCurrentDirectory failed"); + } + } else { + params = g_redisArgMap[argument]->Extract(n, argc, argv); } - } else { - params = g_redisArgMap[argument]->Extract(n, argc, argv); + g_argMap[argument].push_back(params); + n += (int) params.size(); } - g_argMap[argument].push_back(params); - n += (int)params.size(); + } else if (string(argv[n]).substr(0, 1) == "-") { + // Do nothing, the - arguments are passed to redis.c::main() as they are } else { confFile = true; confFilePath = argv[n]; @@ -641,7 +654,9 @@ void ParseCommandLineArguments(int argc, char** argv) { throw std::system_error(GetLastError(), system_category(), "ParseCommandLineArguments: GetCurrentDirectoryA failed"); } - if (confFile) ParseConfFile(confFilePath, cwd, g_argMap); + if (confFile) { + ParseConfFile(confFilePath, cwd, g_argMap); + } // grab directory where RDB/AOF/DAT files will be created so that service install can add access allowed ACE to path string fileCreationDirectory = ".\\"; diff --git a/src/Win32_Interop/Win32_CommandLine.h b/src/Win32_Interop/Win32_CommandLine.h index d2de8baeb5f2..e098513374e0 100644 --- a/src/Win32_Interop/Win32_CommandLine.h +++ b/src/Win32_Interop/Win32_CommandLine.h @@ -64,3 +64,6 @@ const string cNo = "no"; const string cDefaultSyslogIdent = "redis"; const string cDefaultLogfile = "stdout"; +/* List of -- command arguments to be passed to redis::main() unaltered */ +const vector cRedisArgsForMainC = {"help", "version", "test-memory"}; + diff --git a/src/Win32_Interop/Win32_FDAPI.cpp b/src/Win32_Interop/Win32_FDAPI.cpp index cac1f2d48e47..5d164d4c7ac2 100644 --- a/src/Win32_Interop/Win32_FDAPI.cpp +++ b/src/Win32_Interop/Win32_FDAPI.cpp @@ -32,7 +32,7 @@ #include "Win32_ANSI.h" #include "win32_util.h" #include -#include "..\redisLog.h" +#include "Win32_RedisLog.h" using namespace std; #define CATCH_AND_REPORT() catch(const std::exception &){::redisLog(REDIS_WARNING, "FDAPI: std exception");}catch(...){::redisLog(REDIS_WARNING, "FDAPI: other exception");} @@ -1138,7 +1138,7 @@ BOOL ParseStorageAddress(const char *ip, int port, SOCKADDR_STORAGE* pSotrageAdd return TRUE; } -int StorageSize(SOCKADDR_STORAGE *ss) { +int StorageSize(const SOCKADDR_STORAGE *ss) { switch (ss->ss_family) { case AF_INET: return sizeof(SOCKADDR_IN); diff --git a/src/Win32_Interop/Win32_FDAPI.h b/src/Win32_Interop/Win32_FDAPI.h index b33f7069d538..6b67e57ac4cd 100644 --- a/src/Win32_Interop/Win32_FDAPI.h +++ b/src/Win32_Interop/Win32_FDAPI.h @@ -260,7 +260,7 @@ int FDAPI_UpdateAcceptContext( int fd ); // other networking functions BOOL ParseStorageAddress(const char *ip, int port, SOCKADDR_STORAGE* pSotrageAddr); -int StorageSize(SOCKADDR_STORAGE *ss); +int StorageSize(const SOCKADDR_STORAGE *ss); // macroize CRT definitions to point to our own #ifndef FDAPI_NOCRTREDEFS diff --git a/src/Win32_Interop/Win32_Interop.vcxproj b/src/Win32_Interop/Win32_Interop.vcxproj index 913e543c0930..282f797f5561 100644 --- a/src/Win32_Interop/Win32_Interop.vcxproj +++ b/src/Win32_Interop/Win32_Interop.vcxproj @@ -19,7 +19,6 @@ - @@ -29,14 +28,16 @@ + + + - @@ -46,9 +47,13 @@ + + + + @@ -150,8 +155,7 @@ link.exe -dll -noentry resources/EventLog.res -out:$(TargetDir)EventLog.dll MSVCRT - - + DbgHelp.lib;%(AdditionalDependencies) @@ -170,8 +174,7 @@ link.exe -dll -noentry resources/EventLog.res -out:$(TargetDir)EventLog.dll MSVCRT - - + DbgHelp.lib;%(AdditionalDependencies) @@ -198,8 +201,7 @@ link.exe -dll -noentry resources/EventLog.res -out:$(TargetDir)EventLog.dll true - - + DbgHelp.lib;%(AdditionalDependencies) @@ -221,8 +223,7 @@ link.exe -dll -noentry resources/EventLog.res -out:$(TargetDir)EventLog.dll true - - + DbgHelp.lib;%(AdditionalDependencies) diff --git a/src/Win32_Interop/Win32_QFork.cpp b/src/Win32_Interop/Win32_QFork.cpp index b35c1b609887..e6704e36f101 100644 --- a/src/Win32_Interop/Win32_QFork.cpp +++ b/src/Win32_Interop/Win32_QFork.cpp @@ -21,7 +21,6 @@ */ #include "win32_types.h" - #include "Win32_FDAPI.h" #include @@ -42,7 +41,9 @@ #include "Win32_SmartHandle.h" #include "Win32_Service.h" #include "Win32_CommandLine.h" -#include "..\redisLog.h" +#include "Win32_RedisLog.h" +#include "Win32_StackTrace.h" +#include "Win32_ThreadControl.h" #include #include @@ -52,6 +53,7 @@ #include #include #include + using namespace std; #ifndef PAGE_REVERT_TO_FILE_MAP @@ -188,9 +190,9 @@ struct QForkControl { QForkControl* g_pQForkControl; HANDLE g_hQForkControlFileMap; -HANDLE g_hForkedProcess; +HANDLE g_hForkedProcess = 0; DWORD g_systemAllocationGranularity; -int g_SlaveExitCode = 0; // For slave process +int g_ChildExitCode = 0; // For child process bool ReportSpecialSystemErrors(int error) { switch (error) @@ -246,27 +248,27 @@ bool ReportSpecialSystemErrors(int error) { } } -BOOL QForkSlaveInit(HANDLE QForkConrolMemoryMapHandle, DWORD ParentProcessID) { +BOOL QForkChildInit(HANDLE QForkConrolMemoryMapHandle, DWORD ParentProcessID) { try { SmartHandle shParent( OpenProcess(SYNCHRONIZE | PROCESS_DUP_HANDLE, TRUE, ParentProcessID), string("Could not open parent process")); SmartHandle shMMFile(shParent, QForkConrolMemoryMapHandle); - SmartFileView sfvMasterQForkControl( + SmartFileView sfvParentQForkControl( shMMFile, FILE_MAP_COPY, - string("Could not map view of QForkControl in slave. Is system swap file large enough?")); - g_pQForkControl = sfvMasterQForkControl; + string("Could not map view of QForkControl in child. Is system swap file large enough?")); + g_pQForkControl = sfvParentQForkControl; - // duplicate handles and stuff into control structure (master protected by PAGE_WRITECOPY) - SmartHandle dupHeapFileHandle(shParent, sfvMasterQForkControl->heapMemoryMapFile); + // duplicate handles and stuff into control structure (parent protected by PAGE_WRITECOPY) + SmartHandle dupHeapFileHandle(shParent, sfvParentQForkControl->heapMemoryMapFile); g_pQForkControl->heapMemoryMapFile = dupHeapFileHandle; - SmartHandle dupForkedProcessReady(shParent,sfvMasterQForkControl->forkedProcessReady); + SmartHandle dupForkedProcessReady(shParent, sfvParentQForkControl->forkedProcessReady); g_pQForkControl->forkedProcessReady = dupForkedProcessReady; - SmartHandle dupOperationComplete(shParent,sfvMasterQForkControl->operationComplete); + SmartHandle dupOperationComplete(shParent, sfvParentQForkControl->operationComplete); g_pQForkControl->operationComplete = dupOperationComplete; - SmartHandle dupOperationFailed(shParent,sfvMasterQForkControl->operationFailed); + SmartHandle dupOperationFailed(shParent, sfvParentQForkControl->operationFailed); g_pQForkControl->operationFailed = dupOperationFailed; // create section handle on MM file @@ -280,7 +282,7 @@ BOOL QForkSlaveInit(HANDLE QForkConrolMemoryMapHandle, DWORD ParentProcessID) { 0, #endif LODWORD(mmSize), - string("Could not open file mapping object in slave")); + string("Could not open file mapping object in child")); g_pQForkControl->heapMemoryMap = sfmhMapFile; @@ -306,9 +308,9 @@ BOOL QForkSlaveInit(HANDLE QForkConrolMemoryMapHandle, DWORD ParentProcessID) { // execute requested operation if (g_pQForkControl->typeOfOperation == OperationType::otRDB) { - g_SlaveExitCode = do_rdbSave(g_pQForkControl->globalData.filename); + g_ChildExitCode = do_rdbSave(g_pQForkControl->globalData.filename); } else if (g_pQForkControl->typeOfOperation == OperationType::otAOF) { - g_SlaveExitCode = do_aofSave(g_pQForkControl->globalData.filename); + g_ChildExitCode = do_aofSave(g_pQForkControl->globalData.filename); } else if (g_pQForkControl->typeOfOperation == OperationType::otSocket) { LPWSAPROTOCOL_INFO lpProtocolInfo = (LPWSAPROTOCOL_INFO) g_pQForkControl->globalData.protocolInfo; int pipe_write_fd = fdapi_open_osfhandle((intptr_t)g_pQForkControl->globalData.pipe_write_handle, _O_APPEND); @@ -321,7 +323,7 @@ BOOL QForkSlaveInit(HANDLE QForkConrolMemoryMapHandle, DWORD ParentProcessID) { WSA_FLAG_OVERLAPPED); } - g_SlaveExitCode = do_socketSave(g_pQForkControl->globalData.fds, + g_ChildExitCode = do_socketSave(g_pQForkControl->globalData.fds, g_pQForkControl->globalData.numfds, g_pQForkControl->globalData.clientids, pipe_write_fd); @@ -337,21 +339,18 @@ BOOL QForkSlaveInit(HANDLE QForkConrolMemoryMapHandle, DWORD ParentProcessID) { } catch(std::system_error syserr) { if (ReportSpecialSystemErrors(syserr.code().value()) == false) { - ::redisLog(REDIS_WARNING, "QForkSlaveInit: system error caught. error code=0x%08x, message=%s\n", syserr.code().value(), syserr.what()); - g_pQForkControl = NULL; - if (g_pQForkControl != NULL) { - if (g_pQForkControl->operationFailed != NULL) { - SetEvent(g_pQForkControl->operationFailed); - } - } - return FALSE; + ::redisLog(REDIS_WARNING, "QForkChildInit: system error caught. error code=0x%08x, message=%s\n", syserr.code().value(), syserr.what()); } } catch(std::runtime_error runerr) { - ::redisLog(REDIS_WARNING, "QForkSlaveInit: runtime error caught. message=%s\n", runerr.what()); + ::redisLog(REDIS_WARNING, "QForkChildInit: runtime error caught. message=%s\n", runerr.what()); + } + + if (g_pQForkControl != NULL) { + if (g_pQForkControl->operationFailed != NULL) { + SetEvent(g_pQForkControl->operationFailed); + } g_pQForkControl = NULL; - SetEvent(g_pQForkControl->operationFailed); - return FALSE; } return FALSE; } @@ -409,7 +408,7 @@ string GetWorkingDirectory() { return g_MMFDir; } -BOOL QForkMasterInit( __int64 maxheapBytes ) { +BOOL QForkParentInit(__int64 maxheapBytes) { try { // allocate file map for qfork control so it can be passed to the forked process g_hQForkControlFileMap = CreateFileMappingW( @@ -505,13 +504,7 @@ BOOL QForkMasterInit( __int64 maxheapBytes ) { "CreateFileW failed."); } - // There is a strange random failure toawrds the end of mapping the heap in the forked process in the VEH if - // the underlying MMF is not larger than the MM space we are using. This seems to be some sort of - // memory->file allocation granularity issue. Increasing the size of the file (by 16MB) takes care of the - // issue in all cases. - const size_t extraMMF = 64 * cAllocationGranularity; - - SIZE_T mmSize = g_pQForkControl->availableBlocksInHeap * cAllocationGranularity + extraMMF; + SIZE_T mmSize = g_pQForkControl->availableBlocksInHeap * cAllocationGranularity; g_pQForkControl->heapMemoryMap = CreateFileMappingW( g_pQForkControl->heapMemoryMapFile, @@ -600,14 +593,14 @@ BOOL QForkMasterInit( __int64 maxheapBytes ) { } catch(std::system_error syserr) { if (ReportSpecialSystemErrors(syserr.code().value()) == false) { - ::redisLog(REDIS_WARNING, "QForkMasterInit: system error caught. error code=0x%08x, message=%s\n", syserr.code().value(), syserr.what()); + ::redisLog(REDIS_WARNING, "QForkParentInit: system error caught. error code=0x%08x, message=%s\n", syserr.code().value(), syserr.what()); } } catch(std::runtime_error runerr) { - ::redisLog(REDIS_WARNING, "QForkMasterInit: runtime error caught. message=%s\n", runerr.what()); + ::redisLog(REDIS_WARNING, "QForkParentInit: runtime error caught. message=%s\n", runerr.what()); } catch(...) { - ::redisLog(REDIS_WARNING, "QForkMasterInit: other exception caught.\n"); + ::redisLog(REDIS_WARNING, "QForkParentInit: other exception caught.\n"); } return FALSE; } @@ -642,15 +635,24 @@ LONG CALLBACK VectoredHeapMapper(PEXCEPTION_POINTERS info) { else { DWORD err = GetLastError(); - ::redisLog(REDIS_WARNING, "MapViewOfFileEx failed with error 0x%08X.\n", err); + ::redisLog(REDIS_WARNING, "\n\n=== REDIS BUG REPORT START: Cut & paste starting from here ==="); + ::redisLog(REDIS_WARNING, "--- FATAL ERROR MAPPING VIEW OF MAP FILE"); + ::redisLog(REDIS_WARNING, "\t MapViewOfFileEx failed with error 0x%08X.", err); ::redisLog(REDIS_WARNING, "\t startOfMapping 0x%p", startOfMapping); - ::redisLog(REDIS_WARNING, "\t heapStart 0x%p\n", heapStart); - ::redisLog(REDIS_WARNING, "\t heapEnd 0x%p\n", heapEnd); - ::redisLog(REDIS_WARNING, "\t failing access location 0x%p\n", failingMemoryAddress); - ::redisLog(REDIS_WARNING, "\t offset into mmf to start mapping 0x%p\n", mmfOffset); - ::redisLog(REDIS_WARNING, "\t start of new mapping 0x%p\n", startOfMapping); + ::redisLog(REDIS_WARNING, "\t heapStart 0x%p", heapStart); + ::redisLog(REDIS_WARNING, "\t heapEnd 0x%p", heapEnd); + ::redisLog(REDIS_WARNING, "\t failing access location 0x%p", failingMemoryAddress); + ::redisLog(REDIS_WARNING, "\t offset into mmf to start mapping 0x%p", mmfOffset); + ::redisLog(REDIS_WARNING, "\t start of new mapping 0x%p", startOfMapping); ::redisLog(REDIS_WARNING, "\t bytes to map 0x%p\n", bytesToMap); - ::redisLog(REDIS_WARNING, "\t continuing exception handler search\n"); + if (err == 0x000005AF) { + ::redisLog(REDIS_WARNING, "The system paging file is too small for this operation to complete."); + ::redisLog(REDIS_WARNING, "See https://github.com/MSOpenTech/redis/wiki/Memory-Configuration"); + ::redisLog(REDIS_WARNING, "for more information on configuring the system paging file for Redis."); + } + ::redisLog(REDIS_WARNING, "\n=== REDIS BUG REPORT END. Make sure to include from START to END. ===\n\n"); + // Call exit to avoid executing the Unhandled Exceptiont Handler since we don't need a call stack + exit(1); } } } @@ -660,7 +662,8 @@ LONG CALLBACK VectoredHeapMapper(PEXCEPTION_POINTERS info) { // QFork API StartupStatus QForkStartup(int argc, char** argv) { - bool foundSlaveFlag = false; + bool foundChildFlag = false; + int sentinelMode = checkForSentinelMode(argc, argv); HANDLE QForkConrolMemoryMapHandle = NULL; DWORD PPID = 0; __int64 maxheapBytes = -1; @@ -672,8 +675,8 @@ StartupStatus QForkStartup(int argc, char** argv) { g_systemAllocationGranularity = si.dwAllocationGranularity; if (g_argMap.find(cQFork) != g_argMap.end()) { - // slave command line looks like: --QFork [QForkConrolMemoryMap handle] [parent process id] - foundSlaveFlag = true; + // Child command line looks like: --QFork [QForkConrolMemoryMap handle] [parent process id] + foundChildFlag = true; char* endPtr; QForkConrolMemoryMapHandle = (HANDLE)strtoul(g_argMap[cQFork].at(0).at(0).c_str(),&endPtr,10); char* end = NULL; @@ -732,11 +735,13 @@ StartupStatus QForkStartup(int argc, char** argv) { */ int64_t maxMemoryPlusHalf = (3 * maxmemoryBytes) / 2; if( maxmemoryBytes != -1 ) { - maxheapBytes = (maxheapBytes > maxMemoryPlusHalf) ? maxheapBytes : maxMemoryPlusHalf; + if (maxheapBytes < maxMemoryPlusHalf) { + maxheapBytes = maxMemoryPlusHalf; + } } - if( maxheapBytes == -1 ) - { - if (checkForSentinelMode(argc, argv)) { + + if( maxheapBytes == -1 ) { + if (sentinelMode == 1) { // Sentinel mode does not need a large heap. This conserves disk space and page file reservation requirements. maxheapBytes = cSentinelHeapSize; } else { @@ -748,16 +753,16 @@ StartupStatus QForkStartup(int argc, char** argv) { } } - if (foundSlaveFlag) { + if (foundChildFlag) { LPVOID exceptionHandler = AddVectoredExceptionHandler( 1, VectoredHeapMapper ); StartupStatus retVal = StartupStatus::ssFAILED; try { - retVal = QForkSlaveInit( QForkConrolMemoryMapHandle, PPID ) ? StartupStatus::ssSLAVE_EXIT : StartupStatus::ssFAILED; + retVal = QForkChildInit(QForkConrolMemoryMapHandle, PPID) ? StartupStatus::ssCHILD_EXIT : StartupStatus::ssFAILED; } catch (...) { } RemoveVectoredExceptionHandler(exceptionHandler); return retVal; } else { - return QForkMasterInit(maxheapBytes) ? StartupStatus::ssCONTINUE_AS_MASTER : StartupStatus::ssFAILED; + return QForkParentInit(maxheapBytes) ? StartupStatus::ssCONTINUE_AS_PARENT : StartupStatus::ssFAILED; } } @@ -832,7 +837,7 @@ void CopyForkOperationData(OperationType type, LPVOID globalData, int sizeOfGlob throw std::system_error( GetLastError(), system_category(), - "BeginForkOperation: VirtualProtect failed"); + "BeginForkOperation: VirtualProtect failed for the fork control map"); } if (VirtualProtect( g_pQForkControl->heapStart, @@ -842,7 +847,7 @@ void CopyForkOperationData(OperationType type, LPVOID globalData, int sizeOfGlob throw std::system_error( GetLastError(), system_category(), - "BeginForkOperation: VirtualProtect failed"); + "BeginForkOperation: VirtualProtect failed for the heap"); } } @@ -896,19 +901,20 @@ void CreateChildProcess(PROCESS_INFORMATION *pi, char* logfile, DWORD dwCreation throw system_error( GetLastError(), system_category(), - "Problem creating slave process" ); + "Problem creating child process" ); } g_hForkedProcess = pi->hProcess; } typedef void (*CHILD_PID_HOOK)(DWORD pid); -BOOL BeginForkOperation(OperationType type, LPVOID globalData, int sizeOfGlobalData, DWORD* childPID, uint32_t dictHashSeed, char* logfile, CHILD_PID_HOOK pidHook = NULL) { +pid_t BeginForkOperation(OperationType type, LPVOID globalData, int sizeOfGlobalData, uint32_t dictHashSeed, char* logfile, CHILD_PID_HOOK pidHook = NULL) { PROCESS_INFORMATION pi; try { pi.hProcess = INVALID_HANDLE_VALUE; + pi.dwProcessId = -1; - if(pidHook != NULL) { + if (pidHook != NULL) { CreateChildProcess(&pi, logfile, CREATE_SUSPENDED); pidHook(pi.dwProcessId); CopyForkOperationData(type, globalData, sizeOfGlobalData, dictHashSeed); @@ -918,7 +924,6 @@ BOOL BeginForkOperation(OperationType type, LPVOID globalData, int sizeOfGlobalD CreateChildProcess(&pi, logfile, 0); } - *childPID = pi.dwProcessId; CloseHandle(pi.hThread); // wait for "forked" process to map memory @@ -929,7 +934,7 @@ BOOL BeginForkOperation(OperationType type, LPVOID globalData, int sizeOfGlobalD "Forked Process did not respond in a timely manner."); } - return TRUE; + return pi.dwProcessId; } catch(std::system_error syserr) { ::redisLog(REDIS_WARNING, "BeginForkOperation: system error caught. error code=0x%08x, message=%s\n", syserr.code().value(), syserr.what()); @@ -940,34 +945,32 @@ BOOL BeginForkOperation(OperationType type, LPVOID globalData, int sizeOfGlobalD catch(...) { ::redisLog(REDIS_WARNING, "BeginForkOperation: other exception caught.\n"); } - if(pi.hProcess != INVALID_HANDLE_VALUE) { + if (pi.hProcess != INVALID_HANDLE_VALUE) { TerminateProcess(pi.hProcess, 1); } - return FALSE; + return -1; } -BOOL BeginForkOperation_Rdb( +pid_t BeginForkOperation_Rdb( char *filename, LPVOID globalData, int sizeOfGlobalData, - DWORD* childPID, unsigned __int32 dictHashSeed, char* logfile) { strcpy_s(g_pQForkControl->globalData.filename, filename); - return BeginForkOperation(otRDB, globalData, sizeOfGlobalData, childPID, dictHashSeed, logfile); + return BeginForkOperation(otRDB, globalData, sizeOfGlobalData, dictHashSeed, logfile); } -BOOL BeginForkOperation_Aof( +pid_t BeginForkOperation_Aof( char *filename, LPVOID globalData, int sizeOfGlobalData, - DWORD* childPID, unsigned __int32 dictHashSeed, char* logfile) { strcpy_s(g_pQForkControl->globalData.filename, filename); - return BeginForkOperation(otAOF, globalData, sizeOfGlobalData, childPID, dictHashSeed, logfile); + return BeginForkOperation(otAOF, globalData, sizeOfGlobalData, dictHashSeed, logfile); } void BeginForkOperation_Socket_PidHook(DWORD dwProcessId) { @@ -978,14 +981,13 @@ void BeginForkOperation_Socket_PidHook(DWORD dwProcessId) { } } -BOOL BeginForkOperation_Socket( +pid_t BeginForkOperation_Socket( int *fds, int numfds, uint64_t *clientids, int pipe_write_fd, LPVOID globalData, int sizeOfGlobalData, - DWORD* childPID, unsigned __int32 dictHashSeed, char* logfile) { @@ -1001,7 +1003,6 @@ BOOL BeginForkOperation_Socket( return BeginForkOperation(otSocket, globalData, sizeOfGlobalData, - childPID, dictHashSeed, logfile, BeginForkOperation_Socket_PidHook); @@ -1016,8 +1017,20 @@ OperationStatus GetForkOperationStatus() { return OperationStatus::osFAILED; } - if (WaitForSingleObject(g_pQForkControl->forkedProcessReady, 0) == WAIT_OBJECT_0) { - return OperationStatus::osINPROGRESS; + if (g_hForkedProcess && WaitForSingleObject(g_pQForkControl->forkedProcessReady, 0) == WAIT_OBJECT_0) { + // Verify if the child process is still running + if (WaitForSingleObject(g_hForkedProcess, 0) == WAIT_OBJECT_0) { + // The child process is not running, close the handle and report the status + // setting the operationFailed event + CloseHandle(g_hForkedProcess); + g_hForkedProcess = 0; + if (g_pQForkControl->operationFailed != NULL) { + SetEvent(g_pQForkControl->operationFailed); + } + return OperationStatus::osFAILED; + } else { + return OperationStatus::osINPROGRESS; + } } return OperationStatus::osUNSTARTED; @@ -1034,8 +1047,8 @@ BOOL AbortForkOperation() system_category(), "EndForkOperation: Killing forked process failed."); } - g_hForkedProcess = 0; CloseHandle(g_hForkedProcess); + g_hForkedProcess = 0; } return EndForkOperation(NULL); @@ -1117,7 +1130,7 @@ void RejoinCOWPages(HANDLE mmHandle, byte* mmStart, size_t mmSize) { throw std::system_error( GetLastError(), system_category(), - "RejoinCOWPages: MapViewOfFileEx failed. Please upgrade your OS to Win8 or newer."); + "RejoinCOWPages: MapViewOfFileEx failed."); } } } @@ -1136,7 +1149,7 @@ BOOL EndForkOperation(int * pExitCode) { } if (pExitCode != NULL) { - GetExitCodeProcess(g_hForkedProcess, (DWORD*)pExitCode); + GetExitCodeProcess(g_hForkedProcess, (DWORD*)pExitCode); } CloseHandle(g_hForkedProcess); @@ -1319,6 +1332,8 @@ extern "C" InitTimeFunctions(); ParseCommandLineArguments(argc, argv); SetupLogging(); + StackTraceInit(); + InitThreadControl(); } catch (system_error syserr) { exit(-1); } catch (runtime_error runerr) { @@ -1367,16 +1382,16 @@ extern "C" if (IsPersistenceAvailable() == TRUE) { StartupStatus status = QForkStartup(argc, argv); - if (status == ssCONTINUE_AS_MASTER) { + if (status == ssCONTINUE_AS_PARENT) { int retval = redis_main(argc, argv); QForkShutdown(); return retval; - } else if (status == ssSLAVE_EXIT) { - // slave is done - clean up and exit + } else if (status == ssCHILD_EXIT) { + // child is done - clean up and exit QForkShutdown(); - return g_SlaveExitCode; + return g_ChildExitCode; } else if (status == ssFAILED) { - // master or slave failed initialization + // parent or child failed initialization return 1; } else { // unexpected status return diff --git a/src/Win32_Interop/Win32_QFork.h b/src/Win32_Interop/Win32_QFork.h index 1bd4928787bf..160c237faa3a 100644 --- a/src/Win32_Interop/Win32_QFork.h +++ b/src/Win32_Interop/Win32_QFork.h @@ -45,8 +45,8 @@ typedef enum operationStatus { typedef enum startupStatus { ssFAILED = 0, // Something went wrong, exit program with error. - ssCONTINUE_AS_MASTER = 1, // Master qfork initialization complete, continue as master instance. Call QForkShutdown when exiting. - ssSLAVE_EXIT = 2 // Slave completed operation. Call QForkShutdown and exit. + ssCONTINUE_AS_PARENT = 1, // Parent qfork initialization complete, continue as parent instance. Call QForkShutdown when exiting. + ssCHILD_EXIT = 2 // Child completed operation. Call QForkShutdown and exit. } StartupStatus; #define MAX_GLOBAL_DATA 10000 @@ -65,31 +65,28 @@ typedef struct QForkBeginInfo { StartupStatus QForkStartup(int argc, char** argv); BOOL QForkShutdown(); -// For master process use only -BOOL BeginForkOperation_Rdb( +// For parent process use only +pid_t BeginForkOperation_Rdb( char* fileName, LPVOID globalData, int sizeOfGlobalData, - DWORD* childPID, unsigned __int32 dictHashSeed, char* logfile); -BOOL BeginForkOperation_Aof( +pid_t BeginForkOperation_Aof( char* fileName, LPVOID globalData, int sizeOfGlobalData, - DWORD* childPID, unsigned __int32 dictHashSeed, char* logfile); -BOOL BeginForkOperation_Socket( +pid_t BeginForkOperation_Socket( int *fds, int numfds, uint64_t *clientids, int pipe_write_fd, LPVOID globalData, int sizeOfGlobalData, - DWORD* childPID, unsigned __int32 dictHashSeed, char* logfile); diff --git a/src/RedisLog.c b/src/Win32_Interop/Win32_RedisLog.c similarity index 97% rename from src/RedisLog.c rename to src/Win32_Interop/Win32_RedisLog.c index 6d870f38beb7..9778cf6ac7b3 100644 --- a/src/RedisLog.c +++ b/src/Win32_Interop/Win32_RedisLog.c @@ -20,16 +20,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "win32_Interop/win32_types.h" -#include "redisLog.h" +#include "Win32_types.h" +#include "Win32_RedisLog.h" #include #include #include #include #include -#include "redis.h" -#include "win32_Interop/win32Fixes.h" -#include "win32_Interop/Win32_EventLog.h" +#include "../redis.h" +#include "Win32Fixes.h" +#include "Win32_EventLog.h" #include #include diff --git a/src/redisLog.h b/src/Win32_Interop/Win32_RedisLog.h similarity index 100% rename from src/redisLog.h rename to src/Win32_Interop/Win32_RedisLog.h diff --git a/src/Win32_Interop/Win32_StackTrace.cpp b/src/Win32_Interop/Win32_StackTrace.cpp new file mode 100644 index 000000000000..97895d6beb44 --- /dev/null +++ b/src/Win32_Interop/Win32_StackTrace.cpp @@ -0,0 +1,219 @@ +/* +* Copyright (c), Microsoft Open Technologies, Inc. +* All rights reserved. +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* - Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "Win32_StackTrace.h" +#include "Win32_RedisLog.h" +#include +#include +#include + +static IMAGEHLP_SYMBOL64* pSymbol = (IMAGEHLP_SYMBOL64*) malloc(sizeof(IMAGEHLP_SYMBOL64) + MAX_PATH*sizeof(TCHAR)); +static IMAGEHLP_LINE64 line; +static BOOLEAN processingException = FALSE; +static CHAR modulePath[MAX_PATH]; +static LPTOP_LEVEL_EXCEPTION_FILTER defaultTopLevelExceptionHandler = NULL; + +static const char* exceptionDescription(const DWORD& code) +{ + switch (code) { + case EXCEPTION_ACCESS_VIOLATION: return "EXCEPTION_ACCESS_VIOLATION"; + case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"; + case EXCEPTION_BREAKPOINT: return "EXCEPTION_BREAKPOINT"; + case EXCEPTION_DATATYPE_MISALIGNMENT: return "EXCEPTION_DATATYPE_MISALIGNMENT"; + case EXCEPTION_FLT_DENORMAL_OPERAND: return "EXCEPTION_FLT_DENORMAL_OPERAND"; + case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "EXCEPTION_FLT_DIVIDE_BY_ZERO"; + case EXCEPTION_FLT_INEXACT_RESULT: return "EXCEPTION_FLT_INEXACT_RESULT"; + case EXCEPTION_FLT_INVALID_OPERATION: return "EXCEPTION_FLT_INVALID_OPERATION"; + case EXCEPTION_FLT_OVERFLOW: return "EXCEPTION_FLT_OVERFLOW"; + case EXCEPTION_FLT_STACK_CHECK: return "EXCEPTION_FLT_STACK_CHECK"; + case EXCEPTION_FLT_UNDERFLOW: return "EXCEPTION_FLT_UNDERFLOW"; + case EXCEPTION_ILLEGAL_INSTRUCTION: return "EXCEPTION_ILLEGAL_INSTRUCTION"; + case EXCEPTION_IN_PAGE_ERROR: return "EXCEPTION_IN_PAGE_ERROR"; + case EXCEPTION_INT_DIVIDE_BY_ZERO: return "EXCEPTION_INT_DIVIDE_BY_ZERO"; + case EXCEPTION_INT_OVERFLOW: return "EXCEPTION_INT_OVERFLOW"; + case EXCEPTION_INVALID_DISPOSITION: return "EXCEPTION_INVALID_DISPOSITION"; + case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "EXCEPTION_NONCONTINUABLE_EXCEPTION"; + case EXCEPTION_PRIV_INSTRUCTION: return "EXCEPTION_PRIV_INSTRUCTION"; + case EXCEPTION_SINGLE_STEP: return "EXCEPTION_SINGLE_STEP"; + case EXCEPTION_STACK_OVERFLOW: return "EXCEPTION_STACK_OVERFLOW"; + default: return "UNKNOWN EXCEPTION"; + } +} + +/* Returns the index of the last backslash in the file path */ +int GetFilenameStart(CHAR* path) { + int pos = 0; + int found = 0; + if (path != NULL) { + while (path[pos] != '\0' && pos < MAX_PATH) { + if (path[pos] == '\\') { + found = pos + 1; + } + ++pos; + } + } + + return found; +} + +#ifdef _WIN64 +void LogStackTrace() { + BOOL result; + HANDLE thread; + HANDLE process; + CONTEXT context; + STACKFRAME64 stack; + ULONG frame; + DWORD64 dw64Displacement; + DWORD dwDisplacement; + + memset(&stack, 0, sizeof(STACKFRAME64)); + memset(pSymbol, '\0', sizeof(*pSymbol) + MAX_PATH); + memset(&modulePath[0], '\0', sizeof(modulePath)); + line.LineNumber = 0; + + RtlCaptureContext(&context); + process = GetCurrentProcess(); + thread = GetCurrentThread(); + dw64Displacement = 0; + stack.AddrPC.Offset = context.Rip; + stack.AddrPC.Mode = AddrModeFlat; + stack.AddrStack.Offset = context.Rsp; + stack.AddrStack.Mode = AddrModeFlat; + stack.AddrFrame.Offset = context.Rbp; + stack.AddrFrame.Mode = AddrModeFlat; + + for (frame = 0;; frame++){ + result = StackWalk64( + IMAGE_FILE_MACHINE_AMD64, + process, + thread, + &stack, + &context, + NULL, + SymFunctionTableAccess64, + SymGetModuleBase64, + NULL + ); + + pSymbol->MaxNameLength = MAX_PATH; + pSymbol->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + + SymGetSymFromAddr64(process, stack.AddrPC.Offset, &dw64Displacement, pSymbol); + SymGetLineFromAddr64(process, stack.AddrPC.Offset, &dwDisplacement, &line); + + DWORD64 moduleBase = SymGetModuleBase64(process, stack.AddrPC.Offset); + if (moduleBase) + { + GetModuleFileNameA((HINSTANCE) moduleBase, modulePath, MAX_PATH); + } + + redisLog(REDIS_WARNING | REDIS_LOG_RAW, "%s!%s(%s:%d)(0x%08LX, 0x%08LX, 0x%08LX, 0x%08LX)\n", + &modulePath[GetFilenameStart(modulePath)], + pSymbol->Name, + line.FileName, + line.LineNumber, + stack.Params[0], + stack.Params[1], + stack.Params[2], + stack.Params[3] + ); + + if (!result) { + break; + } + } +} +#else +void LogStackTrace() {} +#endif + +void StackTraceInfo() { + redisLog(REDIS_WARNING, "--- STACK TRACE"); + LogStackTrace(); +} + +void ServerInfo() { + redisLog(REDIS_WARNING, "--- INFO OUTPUT"); + // Call antirez routine to log the info output + redisLogRaw(REDIS_WARNING | REDIS_LOG_RAW, genRedisInfoString("all")); +} + +void BugReportEnd(){ + redisLogRaw(REDIS_WARNING, + "\n=== REDIS BUG REPORT END. Make sure to include from START to END. ===\n\n" + " Please report this bug by following the instructions at:\n\n" + " http://github.com/MSOpenTech/redis/wiki/Submitting-an-Issue\n\n" + " Suspect RAM error? Use redis-server --test-memory to verify it.\n\n" + ); +} + +LONG WINAPI UnhandledExceptiontHandler(PEXCEPTION_POINTERS info) { + if (!processingException) { + try { + const char* exDescription = "Exception code not available"; + processingException = true; + if (info->ExceptionRecord != NULL && info->ExceptionRecord->ExceptionCode != NULL) { + exDescription = exceptionDescription(info->ExceptionRecord->ExceptionCode); + } + + // Call antirez routine to log the start of the bug report + bugReportStart(); + redisLog(REDIS_WARNING, "--- %s", exDescription); + StackTraceInfo(); + //ServerInfo(); + BugReportEnd(); + processingException = false; + } + catch (...) {}; + } + + if (defaultTopLevelExceptionHandler != NULL) { + defaultTopLevelExceptionHandler(info); + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +/* Handler to trap abort() calls */ +extern "C" void AbortHandler(int signal_number) { + bugReportStart(); + redisLog(REDIS_WARNING, "--- ABORT"); + StackTraceInfo(); + BugReportEnd(); +} + +void InitSymbols() { + // Preload symbols so they will be available in case of out-of-memory exception + SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_UNDNAME); + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + HANDLE process = GetCurrentProcess(); + SymInitialize(process, NULL, TRUE); +} + +void StackTraceInit(void) { + InitSymbols(); + // Global handler for unhandled exceptions + defaultTopLevelExceptionHandler = SetUnhandledExceptionFilter(UnhandledExceptiontHandler); + // Handler for abort() + signal(SIGABRT, &AbortHandler); +} diff --git a/src/Win32_Interop/Win32_StackTrace.h b/src/Win32_Interop/Win32_StackTrace.h new file mode 100644 index 000000000000..36638d5f8849 --- /dev/null +++ b/src/Win32_Interop/Win32_StackTrace.h @@ -0,0 +1,32 @@ +/* +* Copyright (c), Microsoft Open Technologies, Inc. +* All rights reserved. +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* - Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* - Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#pragma once + +#include "win32_types.h" +#include + +void StackTraceInit(void); + +extern "C" typedef char *sds; +extern "C" sds genRedisInfoString(char *section); +extern "C" void bugReportStart(void); \ No newline at end of file diff --git a/src/Win32_Interop/Win32_ThreadControl.c b/src/Win32_Interop/Win32_ThreadControl.c new file mode 100644 index 000000000000..d9b0647944c0 --- /dev/null +++ b/src/Win32_Interop/Win32_ThreadControl.c @@ -0,0 +1,111 @@ +/* + * Copyright (c), Microsoft Open Technologies, Inc. + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + + +volatile LONG g_NumWorkerThreads = 0; + +// Safe mode means the threads are not touching the heap, or they are suspended because of an explicit suspension request +// Threads in safe mode because they are not touching the heap will block if trying to transition to unsafe mode while a suspension is requested +volatile LONG g_NumWorkerThreadsInSafeMode = 0; + +volatile LONG g_SuspensionRequested = 0; +HANDLE g_hResumeFromSuspension; + +CRITICAL_SECTION g_ThreadControlMutex; + + +void InitThreadControl() { + InitializeCriticalSection(&g_ThreadControlMutex); + g_hResumeFromSuspension = CreateEvent(NULL, TRUE, TRUE, NULL); + if (!g_hResumeFromSuspension) { + exit(GetLastError()); + } +} + +void IncrementWorkerThreadCount() { + EnterCriticalSection(&g_ThreadControlMutex); + g_NumWorkerThreads++; + LeaveCriticalSection(&g_ThreadControlMutex); +} + +void DecrementWorkerThreadCount() { + EnterCriticalSection(&g_ThreadControlMutex); + g_NumWorkerThreads--; + LeaveCriticalSection(&g_ThreadControlMutex); +} + + +// Returns TRUE if threads are already in safe mode or suspended +BOOL SuspensionCompleted() { + BOOL result; + EnterCriticalSection(&g_ThreadControlMutex); + result = (g_NumWorkerThreadsInSafeMode == g_NumWorkerThreads); + LeaveCriticalSection(&g_ThreadControlMutex); + return result; +} + +// This is meant to be called from the main thread only. +void RequestSuspension() { + if (!g_SuspensionRequested) { + if (!ResetEvent(g_hResumeFromSuspension)) { + exit(GetLastError()); + } + _InterlockedOr(&g_SuspensionRequested, 1); + } +} + +void ResumeFromSuspension() { + // This is meant to be called from the main thread only. + assert(g_SuspensionRequested && SuspensionCompleted()); + + _InterlockedAnd(&g_SuspensionRequested, 0); + if (!SetEvent(g_hResumeFromSuspension)) { + exit(GetLastError()); + } +} + +void WorkerThread_EnterSafeMode() { + EnterCriticalSection(&g_ThreadControlMutex); + g_NumWorkerThreadsInSafeMode++; + LeaveCriticalSection(&g_ThreadControlMutex); +} + +void WorkerThread_ExitSafeMode() { + for(;;) { + EnterCriticalSection(&g_ThreadControlMutex); + if (g_SuspensionRequested) { + LeaveCriticalSection(&g_ThreadControlMutex); + if (WaitForSingleObject(g_hResumeFromSuspension, INFINITE) != WAIT_OBJECT_0) { + exit(GetLastError()); + } + continue; + } else { + g_NumWorkerThreadsInSafeMode--; + LeaveCriticalSection(&g_ThreadControlMutex); + break; + } + } +} + diff --git a/msvs/RedisLog.h b/src/Win32_Interop/Win32_ThreadControl.h similarity index 75% rename from msvs/RedisLog.h rename to src/Win32_Interop/Win32_ThreadControl.h index 13ba4f7f447e..d79d5e1275d9 100644 --- a/msvs/RedisLog.h +++ b/src/Win32_Interop/Win32_ThreadControl.h @@ -19,19 +19,25 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #pragma once -/* Log levels */ -#define REDIS_DEBUG 0 -#define REDIS_VERBOSE 1 -#define REDIS_NOTICE 2 -#define REDIS_WARNING 3 -#define REDIS_LOG_RAW (1<<10) /* Modifier to log without timestamp */ +#ifdef __cplusplus +extern "C" { +#endif + + +void InitThreadControl(); +void IncrementWorkerThreadCount(); +void DecrementWorkerThreadCount(); +void RequestSuspension(); +BOOL SuspensionCompleted(); +void ResumeFromSuspension(); -#define REDIS_MAX_LOGMSG_LEN 1024 /* Default maximum length of syslog messages */ +void WorkerThread_EnterSafeMode(); +void WorkerThread_ExitSafeMode(); -void redisLog(int level, const char *fmt, ...); -void redisLogRaw(int level, const char *msg); -void redisLogFromHandler(int level, const char *msg); -void SetVerbosity(int verbosity); \ No newline at end of file +#ifdef __cplusplus +} +#endif diff --git a/src/Win32_Interop/Win32_dlmalloc.c b/src/Win32_Interop/Win32_dlmalloc.c index b4559c8e4fe4..fded58030d7e 100644 --- a/src/Win32_Interop/Win32_dlmalloc.c +++ b/src/Win32_Interop/Win32_dlmalloc.c @@ -1702,10 +1702,6 @@ static FORCEINLINE void* win32mmap(size_t size) { #else void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); #endif - if( ptr == NULL ) - { - printf( "VirtualAlloc/COWAlloc fail!\n"); - } return (ptr != 0)? ptr: MFAIL; } @@ -1716,10 +1712,6 @@ static FORCEINLINE void* win32direct_mmap(size_t size) { #else void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, PAGE_READWRITE); #endif - if( ptr == NULL ) - { - printf( "VirtualAlloc/COWAlloc fail!\n"); - } return (ptr != 0)? ptr: MFAIL; } diff --git a/src/Win32_Interop/Win32_service.cpp b/src/Win32_Interop/Win32_service.cpp index d6ab2036970a..0387dd7c4e93 100644 --- a/src/Win32_Interop/Win32_service.cpp +++ b/src/Win32_Interop/Win32_service.cpp @@ -68,7 +68,7 @@ this should preceed the other arguments passed to redis. For instance: #include #include #include -#include "..\redisLog.h" +#include "Win32_RedisLog.h" #include "Win32_CommandLine.h" using namespace std; @@ -483,10 +483,10 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam) { main(argc, argv); for (int a = 0; a < argc; a++) { - delete argv[a]; + delete[] argv[a]; argv[a] = nullptr; } - delete argv; + delete[] argv; argv = nullptr; SetEvent(g_ServiceStoppedEvent); diff --git a/src/Win32_Interop/win32_rfdmap.cpp b/src/Win32_Interop/win32_rfdmap.cpp index e447cbccebfe..2375a6a68be2 100644 --- a/src/Win32_Interop/win32_rfdmap.cpp +++ b/src/Win32_Interop/win32_rfdmap.cpp @@ -22,139 +22,126 @@ #include "win32_types.h" - #include "win32_rfdmap.h" RFDMap& RFDMap::getInstance() { - static RFDMap instance; // Instantiated on first use. Guaranteed to be destroyed. + static RFDMap instance; // Instantiated on first use. Guaranteed to be destroyed. return instance; } -RFDMap::RFDMap() { maxRFD = minRFD; }; +RFDMap::RFDMap() { + InitializeCriticalSection(&mutex); + maxRFD = minRFD; +} RFD RFDMap::getNextRFDAvailable() { - if( RFDRecyclePool.empty() == false ) { - int RFD = RFDRecyclePool.front(); - RFDRecyclePool.pop(); - return RFD; - } else { - maxRFD = minRFD + (int)SocketToRFDMap.size() + (int)PosixFDToRFDMap.size(); - return maxRFD; - } + RFD rfd; + EnterCriticalSection(&mutex); + if (RFDRecyclePool.empty() == false) { + rfd = RFDRecyclePool.front(); + RFDRecyclePool.pop(); + } else { + maxRFD = minRFD + (int) SocketToRFDMap.size() + (int) PosixFDToRFDMap.size(); + rfd = maxRFD; + } + LeaveCriticalSection(&mutex); + return rfd; } RFD RFDMap::addSocket(SOCKET s) { - if (SocketToRFDMap.find(s) != SocketToRFDMap.end()) { - return invalidRFD; - } - - RFD rfd = getNextRFDAvailable(); - SocketToRFDMap[s] = rfd; - RFDToSocketMap[rfd] = s; - return rfd; + RFD rfd; + EnterCriticalSection(&mutex); + if (SocketToRFDMap.find(s) != SocketToRFDMap.end()) { + rfd = invalidRFD; + } else { + rfd = getNextRFDAvailable(); + SocketToRFDMap[s] = rfd; + RFDToSocketMap[rfd] = s; + } + LeaveCriticalSection(&mutex); + return rfd; } -void RFDMap::removeSocket(SOCKET s) { - S2RFDIterator mit = SocketToRFDMap.find(s); - if(mit == SocketToRFDMap.end()) { -// redisLog( REDIS_DEBUG, "RFDMap::removeSocket() - failed to find socket!" ); - return; +void RFDMap::removeSocket(SOCKET s) { + EnterCriticalSection(&mutex); + S2RFDIterator mit = SocketToRFDMap.find(s); + if (mit != SocketToRFDMap.end()) { + RFD rfd = (*mit).second; + RFDRecyclePool.push(rfd); + RFDToSocketMap.erase(rfd); + SocketToRFDMap.erase(s); } - RFD rfd = (*mit).second; - RFDRecyclePool.push(rfd); - RFDToSocketMap.erase(rfd); - SocketToRFDMap.erase(s); + LeaveCriticalSection(&mutex); } RFD RFDMap::addPosixFD(int posixFD) { - if (PosixFDToRFDMap.find(posixFD) != PosixFDToRFDMap.end()) { -// redisLog( REDIS_DEBUG, "RFDMap::addPosixFD() - posixFD already exists!" ); - return invalidRFD; - } - - RFD rfd = getNextRFDAvailable(); - PosixFDToRFDMap[posixFD] = rfd; - RFDToPosixFDMap[rfd] = posixFD; - return rfd; + RFD rfd; + EnterCriticalSection(&mutex); + if (PosixFDToRFDMap.find(posixFD) != PosixFDToRFDMap.end()) { + rfd = invalidRFD; + } else { + rfd = getNextRFDAvailable(); + PosixFDToRFDMap[posixFD] = rfd; + RFDToPosixFDMap[rfd] = posixFD; + } + LeaveCriticalSection(&mutex); + return rfd; } -void RFDMap::removePosixFD(int posixFD) { - PosixFD2RFDIterator mit = PosixFDToRFDMap.find(posixFD); - if(mit == PosixFDToRFDMap.end()) { -// redisLog( REDIS_DEBUG, "RFDMap::removePosixFD() - failed to find posix FD!" ); - return; +void RFDMap::removePosixFD(int posixFD) { + EnterCriticalSection(&mutex); + PosixFD2RFDIterator mit = PosixFDToRFDMap.find(posixFD); + if (mit != PosixFDToRFDMap.end()) { + RFD rfd = (*mit).second; + RFDRecyclePool.push(rfd); + RFDToPosixFDMap.erase(rfd); + PosixFDToRFDMap.erase(posixFD); } - RFD rfd = (*mit).second; - RFDRecyclePool.push(rfd); - RFDToPosixFDMap.erase(rfd); - PosixFDToRFDMap.erase(posixFD); + LeaveCriticalSection(&mutex); } SOCKET RFDMap::lookupSocket(RFD rfd) { - if (RFDToSocketMap.find(rfd) != RFDToSocketMap.end()) { - return RFDToSocketMap[rfd]; - } else { -// redisLog( REDIS_DEBUG, "RFDMap::lookupSocket() - failed to find socket!" ); - return INVALID_SOCKET; - } + SOCKET socket = INVALID_SOCKET; + EnterCriticalSection(&mutex); + if (RFDToSocketMap.find(rfd) != RFDToSocketMap.end()) { + socket = RFDToSocketMap[rfd]; + } + LeaveCriticalSection(&mutex); + return socket; } int RFDMap::lookupPosixFD(RFD rfd) { - if (RFDToPosixFDMap.find(rfd) != RFDToPosixFDMap.end()) { - return RFDToPosixFDMap[rfd]; - } else if (rfd >= 0 && rfd <= 2) { - return rfd; - } - else { -// redisLog( REDIS_DEBUG, "RFDMap::lookupPosixFD() - failed to find posix FD!" ); - return -1; - } -} - -RFD RFDMap::lookupRFD(SOCKET s) { - if (SocketToRFDMap.find(s) != SocketToRFDMap.end()) { - return SocketToRFDMap[s]; - } else { -// redisLog( REDIS_DEBUG, "RFDMap::lookupFD() - failed to map SOCKET to RFD!" ); - return invalidRFD; - } -} - -RFD RFDMap::lookupRFD(int posixFD) { - if (PosixFDToRFDMap.find(posixFD) != PosixFDToRFDMap.end()) { - return PosixFDToRFDMap[posixFD]; - } else { -// redisLog( REDIS_DEBUG, "RFDMap::lookupFD() - failed to map posixFD to RFD!" ); - return invalidRFD; - } -} - -RFD RFDMap::getMinRFD() { - return minRFD; -} - -RFD RFDMap::getMaxRFD() { - return maxRFD; + int posixFD = -1; + EnterCriticalSection(&mutex); + if (RFDToPosixFDMap.find(rfd) != RFDToPosixFDMap.end()) { + posixFD = RFDToPosixFDMap[rfd]; + } else if (rfd >= 0 && rfd <= 2) { + posixFD = rfd; + } + LeaveCriticalSection(&mutex); + return posixFD; } -bool RFDMap::SetSocketState( SOCKET s, RedisSocketState state ) -{ +bool RFDMap::SetSocketState(SOCKET s, RedisSocketState state) { + bool result = false; + EnterCriticalSection(&mutex); S2StateIterator sit = SocketToStateMap.find(s); - if(sit != SocketToStateMap.end() ) { + if (sit != SocketToStateMap.end()) { SocketToStateMap[s] = state; - return true; - } else { - return false; + result = true; } + LeaveCriticalSection(&mutex); + return result; } -bool RFDMap::GetSocketState( SOCKET s, RedisSocketState& state ) -{ +bool RFDMap::GetSocketState(SOCKET s, RedisSocketState& state) { + bool result = false; + EnterCriticalSection(&mutex); S2StateIterator sit = SocketToStateMap.find(s); - if(sit != SocketToStateMap.end() ) { + if (sit != SocketToStateMap.end()) { state = SocketToStateMap[s]; - return true; - } else { - return false; + result = true; } + LeaveCriticalSection(&mutex); + return result; } diff --git a/src/Win32_Interop/win32_rfdmap.h b/src/Win32_Interop/win32_rfdmap.h index 7625132ee4e5..227a02745d71 100644 --- a/src/Win32_Interop/win32_rfdmap.h +++ b/src/Win32_Interop/win32_rfdmap.h @@ -23,15 +23,12 @@ #pragma once #include - #define INCL_WINSOCK_API_PROTOTYPES 0 // Important! Do not include Winsock API definitions to avoid conflicts with API entry points defnied below. #include #include "ws2tcpip.h" - -//#include - #include #include + using namespace std; typedef struct { @@ -69,65 +66,56 @@ class RFDMap { private: RFDMap(); - RFDMap(RFDMap const&); // Don't implement to guarantee singleton semantics - void operator=(RFDMap const&); // Don't implement to guarantee singleton semantics + RFDMap(RFDMap const&); // Don't implement to guarantee singleton semantics + void operator=(RFDMap const&); // Don't implement to guarantee singleton semantics private: - SocketToRFDMapType SocketToRFDMap; - SocketToStateMapType SocketToStateMap; + SocketToRFDMapType SocketToRFDMap; + SocketToStateMapType SocketToStateMap; PosixFDToRFDMapType PosixFDToRFDMap; - RFDToSocketMapType RFDToSocketMap; - RFDToPosixFDMapType RFDToPosixFDMap; - RFDRecyclePoolType RFDRecyclePool; + RFDToSocketMapType RFDToSocketMap; + RFDToPosixFDMapType RFDToPosixFDMap; + RFDRecyclePoolType RFDRecyclePool; -public: - const static int minRFD = 3; // 0, 1 and 2 are reserved for stdin, stdout and stderr +private: + const static int minRFD = 3; // 0, 1 and 2 are reserved for stdin, stdout and stderr RFD maxRFD; - const static int invalidRFD = -1; + CRITICAL_SECTION mutex; + +public: + const static int invalidRFD = -1; private: - /* Gets the next available Redis File Descriptor. Redis File Descriptors are always - non-negative integers, with the first three being reserved for stdin(0), - stdout(1) and stderr(2). */ - RFD getNextRFDAvailable(); + /* Gets the next available Redis File Descriptor. Redis File Descriptors are always + non-negative integers, with the first three being reserved for stdin(0), + stdout(1) and stderr(2). */ + RFD getNextRFDAvailable(); public: - /* Adds a socket to the socket map. Returns the redis file descriptor value for - the socket. Returns invalidRFD if the socket is already added to the - collection. */ - RFD addSocket(SOCKET s); + /* Adds a socket to the socket map. Returns the redis file descriptor value for + the socket. Returns invalidRFD if the socket is already added to the + collection. */ + RFD addSocket(SOCKET s); - /* Removes a socket from the list of sockets. Also removes the associated - file descriptor. */ - void removeSocket(SOCKET s); + /* Removes a socket from the list of sockets. Also removes the associated + file descriptor. */ + void removeSocket(SOCKET s); - /* Adds a posixFD (used with low-level CRT posix file functions) to the posixFD map. Returns + /* Adds a posixFD (used with low-level CRT posix file functions) to the posixFD map. Returns the redis file descriptor value for the posixFD. Returns invalidRFD if the posicFD is already added to the collection. */ - RFD addPosixFD(int posixFD); - - /* Removes a socket from the list of sockets. Also removes the associated - file descriptor. */ - void removePosixFD(int posixFD); + RFD addPosixFD(int posixFD); - /* Returns the socket associated with a file descriptor. */ - SOCKET lookupSocket(RFD rfd); + /* Removes a socket from the list of sockets. Also removes the associated + file descriptor. */ + void removePosixFD(int posixFD); /* Returns the socket associated with a file descriptor. */ - int lookupPosixFD(RFD rfd); - - /* Returns the RFD associated with a socket. */ - RFD lookupRFD(SOCKET s); + SOCKET lookupSocket(RFD rfd); - /* Returns the RFD associated with a posix FD. */ - RFD lookupRFD(int posixFD); - - /* Returns the smallest RFD available */ - RFD getMinRFD(); - - /* Returns the largest FD allocated so far */ - RFD getMaxRFD(); + /* Returns the socket associated with a file descriptor. */ + int lookupPosixFD(RFD rfd); - bool SetSocketState( SOCKET s, RedisSocketState state ); - bool GetSocketState( SOCKET s, RedisSocketState& state ); + bool SetSocketState(SOCKET s, RedisSocketState state); + bool GetSocketState(SOCKET s, RedisSocketState& state); }; diff --git a/src/Win32_Interop/win32_types.h b/src/Win32_Interop/win32_types.h index 5241ed79628b..d0368b289a5b 100644 --- a/src/Win32_Interop/win32_types.h +++ b/src/Win32_Interop/win32_types.h @@ -51,17 +51,17 @@ typedef __int64 PORT_LONGLONG; typedef unsigned __int64 PORT_ULONGLONG; typedef double PORT_LONGDOUBLE; -#if defined(_WIN64) +#ifdef _WIN64 typedef __int64 ssize_t; typedef __int64 PORT_LONG; typedef unsigned __int64 PORT_ULONG; #else - typedef _W64 long ssize_t; - typedef _W64 long PORT_LONG; - typedef _W64 unsigned long PORT_ULONG; + typedef long ssize_t; + typedef long PORT_LONG; + typedef unsigned long PORT_ULONG; #endif -#if defined(_WIN64) +#ifdef _WIN64 #define PORT_LONG_MAX _I64_MAX #define PORT_LONG_MIN _I64_MIN #define PORT_ULONG_MAX _UI64_MAX @@ -72,6 +72,6 @@ typedef double PORT_LONGDOUBLE; #endif /* The maximum possible size_t value has all bits set */ -#define MAX_SIZE_T (~(size_t)0) - +#define MAX_SIZE_T (~(size_t)0) +typedef int pid_t; \ No newline at end of file diff --git a/src/Win32_Interop/win32_wsiocp.c b/src/Win32_Interop/win32_wsiocp.c index f4ea61cdca8a..ee9ed7a8448f 100644 --- a/src/Win32_Interop/win32_wsiocp.c +++ b/src/Win32_Interop/win32_wsiocp.c @@ -31,7 +31,6 @@ #include #include - static void *iocpState; static HANDLE iocph; static fnGetSockState * aeGetSockState; @@ -94,7 +93,7 @@ int aeWinQueueAccept(int listenfd) { return -1; } - return TRUE; + return 0; } /* listen using extension function to get faster accepts */ @@ -126,7 +125,7 @@ int aeWinListen(int rfd, int backlog) { /* return the queued accept socket */ int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len) { aeSockState *sockstate; - int acceptsock; + int acceptfd; int result; SOCKADDR *plocalsa; SOCKADDR *premotesa; @@ -139,7 +138,6 @@ int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len) { return SOCKET_ERROR; } - areq = sockstate->reqs; if (areq == NULL) { errno = EWOULDBLOCK; @@ -148,9 +146,9 @@ int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len) { sockstate->reqs = areq->next; - acceptsock = (int)areq->accept; + acceptfd = (int)areq->accept; - result = FDAPI_UpdateAcceptContext(acceptsock); + result = FDAPI_UpdateAcceptContext(acceptfd); if (result == SOCKET_ERROR) { errno = WSAGetLastError(); return SOCKET_ERROR; @@ -158,7 +156,7 @@ int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len) { locallen = *len; FDAPI_GetAcceptExSockaddrs( - acceptsock, + acceptfd, areq->buf, 0, sizeof(struct sockaddr_storage), @@ -170,10 +168,10 @@ int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len) { memcpy(sa, premotesa, locallen); *len = locallen; - aeWinSocketAttach(acceptsock); + aeWinSocketAttach(acceptfd); // Save remote address to support aeWinGetPeerName() - if ((acceptsockstate = aeGetExistingSockState(iocpState, acceptsock)) == NULL) { + if ((acceptsockstate = aeGetExistingSockState(iocpState, acceptfd)) == NULL) { errno = WSAEINVAL; return SOCKET_ERROR; } @@ -187,7 +185,7 @@ int aeWinAccept(int fd, struct sockaddr *sa, socklen_t *len) { return SOCKET_ERROR; } - return acceptsock; + return acceptfd; } int aeWinGetPeerName(int fd, struct sockaddr *addr, socklen_t * addrlen) { diff --git a/src/Win32_Interop/win32fixes.c b/src/Win32_Interop/win32fixes.c index 3f310d483a49..6aef31d0181b 100644 --- a/src/Win32_Interop/win32fixes.c +++ b/src/Win32_Interop/win32fixes.c @@ -20,6 +20,7 @@ #include #include //#include +#include "Win32_ThreadControl.h" /* Redefined here to avoid redis.h so it can be used in other projects */ #define REDIS_NOTUSED(V) ((void) V) @@ -149,12 +150,16 @@ typedef struct thread_params /* Proxy function by windows thread requirements */ static unsigned __stdcall win32_proxy_threadproc(void *arg) { - - thread_params *p = (thread_params *) arg; - p->func(p->arg); - - /* Dealocate params */ - free(p); + IncrementWorkerThreadCount(); + __try { + thread_params *p = (thread_params *) arg; + p->func(p->arg); + + /* Dealocate params */ + free(p); + } __finally { + DecrementWorkerThreadCount(); + } _endthreadex(0); return 0; @@ -679,7 +684,7 @@ int truncate(const char *path, PORT_LONGLONG length) { toTruncate = CreateFileA(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (toTruncate != INVALID_HANDLE_VALUE) { newSize.QuadPart = length; - if (FALSE == SetFilePointerEx(toTruncate, newSize, NULL, FILE_BEGIN)) { + if (FALSE == (SetFilePointerEx(toTruncate, newSize, NULL, FILE_BEGIN) && SetEndOfFile(toTruncate))) { errno = ENOENT; return -1; } else { diff --git a/src/Win32_Interop/win32fixes.h b/src/Win32_Interop/win32fixes.h index 7137b1840473..bf4aefe09241 100644 --- a/src/Win32_Interop/win32fixes.h +++ b/src/Win32_Interop/win32fixes.h @@ -178,7 +178,6 @@ int getrusage(int who, struct rusage * rusage); #endif /*SIG_SETMASK*/ typedef void (*__p_sig_fn_t)(int); -typedef DWORD pid_t; #ifndef _SIGSET_T_ #define _SIGSET_T_ diff --git a/src/aof.c b/src/aof.c index d70e44e49dd8..c8597f250017 100644 --- a/src/aof.c +++ b/src/aof.c @@ -220,14 +220,14 @@ void stopAppendOnly(void) { server.aof_state = REDIS_AOF_OFF; /* rewrite operation in progress? kill it, wait child exit */ if (server.aof_child_pid != -1) { - redisLog(REDIS_NOTICE, "Killing running AOF rewrite child: %Id", /* PORTABILITY FIX %ld -> %Id */ + redisLog(REDIS_NOTICE, "Killing running AOF rewrite child: %Id", WIN_PORT_FIX /* %ld -> %Id */ (PORT_LONG) server.aof_child_pid); #ifdef _WIN32 AbortForkOperation(); #else { int statloc; - if (kill(server.aof_child_pid,SIGUSR1) != -1) + if (kill(server.aof_child_pid,SIGUSR1) != -1) wait3(&statloc,0,NULL); } #endif @@ -1289,36 +1289,6 @@ void aofClosePipes(void) { * finally will rename(2) the temp file in the actual file name. * The the new file is reopened as the new append only file. Profit! */ -#ifdef _WIN32 -int rewriteAppendOnlyFileBackground(void) { - PORT_LONGLONG start; - char tmpfile[256]; - - if (server.aof_child_pid != -1) return REDIS_ERR; - start = ustime(); - - snprintf(tmpfile,256,"temp-rewriteaof-bg-%d.aof", (int) getpid()); - if (BeginForkOperation_Aof(tmpfile, &server, sizeof(server), &server.aof_child_pid, dictGetHashFunctionSeed(), server.logfile) == FALSE) { - redisLog(REDIS_WARNING, - "Can't rewrite append only file in background: fork: %s", - strerror(errno)); - return REDIS_ERR; - } - server.stat_fork_time = ustime()-start; - - redisLog(REDIS_NOTICE, - "Background append only file rewriting started by pid %d",server.aof_child_pid); - server.aof_rewrite_scheduled = 0; - server.aof_rewrite_time_start = time(NULL); - updateDictResizePolicy(); - /* We set appendseldb to -1 in order to force the next call to the - * feedAppendOnlyFile() to issue a SELECT command, so the differences - * accumulated by the parent into server.aof_rewrite_buf will start - * with a SELECT statement and it will be safe to merge. */ - server.aof_selected_db = -1; - return REDIS_OK; -} -#else int rewriteAppendOnlyFileBackground(void) { pid_t childpid; PORT_LONGLONG start; @@ -1326,13 +1296,21 @@ int rewriteAppendOnlyFileBackground(void) { if (server.aof_child_pid != -1) return REDIS_ERR; if (aofCreatePipes() != REDIS_OK) return REDIS_ERR; start = ustime(); + +#ifndef _WIN32 if ((childpid = fork()) == 0) { +#endif char tmpfile[256]; - /* Child */ +#ifndef _WIN32 + /* Child */ closeListeningSockets(0); redisSetProcTitle("redis-aof-rewrite"); +#endif snprintf(tmpfile,256,"temp-rewriteaof-bg-%d.aof", (int) getpid()); +#ifdef _WIN32 + childpid = BeginForkOperation_Aof(tmpfile, &server, sizeof(server), dictGetHashFunctionSeed(), server.logfile); +#else if (rewriteAppendOnlyFile(tmpfile) == REDIS_OK) { size_t private_dirty = zmalloc_get_private_dirty(); @@ -1346,6 +1324,7 @@ int rewriteAppendOnlyFileBackground(void) { exitFromChild(1); } } else { +#endif /* Parent */ server.stat_fork_time = ustime()-start; server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */ @@ -1369,10 +1348,11 @@ int rewriteAppendOnlyFileBackground(void) { server.aof_selected_db = -1; replicationScriptCacheFlush(); return REDIS_OK; +#ifndef _WIN32 } +#endif return REDIS_OK; /* unreached */ } -#endif void bgrewriteaofCommand(redisClient *c) { if (server.aof_child_pid != -1) { diff --git a/src/bio.c b/src/bio.c index e187942dea09..381fa9b1da8a 100644 --- a/src/bio.c +++ b/src/bio.c @@ -64,6 +64,7 @@ #include "bio.h" #ifdef _WIN32 #include "win32_Interop/win32fixes.h" +#include "Win32_Interop/Win32_ThreadControl.h" #endif static pthread_t bio_threads[REDIS_BIO_NUM_OPS]; @@ -158,6 +159,7 @@ void *bioProcessBackgroundJobs(void *arg) { #endif pthread_mutex_lock(&bio_mutex[type]); + /* Block SIGALRM so we are sure that only the main thread will * receive the watchdog signal. */ sigemptyset(&sigset); @@ -171,7 +173,11 @@ void *bioProcessBackgroundJobs(void *arg) { /* The loop always starts with the lock hold. */ if (listLength(bio_jobs[type]) == 0) { + WIN32_ONLY(WorkerThread_EnterSafeMode()); pthread_cond_wait(&bio_condvar[type],&bio_mutex[type]); + WIN32_ONLY(pthread_mutex_unlock(&bio_mutex[type])); + WIN32_ONLY(WorkerThread_ExitSafeMode()); + WIN32_ONLY(pthread_mutex_lock(&bio_mutex[type])); continue; } /* Pop the job from the queue. */ diff --git a/src/debug.c b/src/debug.c index dbf162ecca23..14b4f424f430 100644 --- a/src/debug.c +++ b/src/debug.c @@ -481,8 +481,12 @@ void _redisAssertWithInfo(redisClient *c, robj *o, char *estr, char *file, int l void _redisPanic(char *msg, char *file, int line) { bugReportStart(); redisLog(REDIS_WARNING,"------------------------------------------------"); +#ifdef _WIN32 + redisLog(REDIS_WARNING, "Fatal Error: %s #%s:%d", msg, file, line); +#else redisLog(REDIS_WARNING,"!!! Software Failure. Press left mouse button to continue"); redisLog(REDIS_WARNING,"Guru Meditation: %s #%s:%d",msg,file,line); +#endif #ifdef HAVE_BACKTRACE redisLog(REDIS_WARNING,"(forcing SIGSEGV in order to print the stack trace)"); #endif diff --git a/src/latency.c b/src/latency.c index d978cfada002..68b2acd32c04 100644 --- a/src/latency.c +++ b/src/latency.c @@ -547,7 +547,7 @@ sds latencyCommandGenSparkeline(char *event, struct latencyTimeSeries *ts) { } graph = sdscatprintf(graph, - "%s - high %Iu ms, low %Iu ms (all time high %Iu ms)\n", event, /* PORTABILITY FIX %ld -> %Id, %lu -> %Iu */ + "%s - high %Iu ms, low %Iu ms (all time high %Iu ms)\n", event, WIN_PORT_FIX /* %ld -> %Id, %lu -> %Iu */ (PORT_ULONG) max, (PORT_ULONG) min, (PORT_ULONG) ts->max); for (j = 0; j < LATENCY_GRAPH_COLS; j++) graph = sdscatlen(graph,"-",1); diff --git a/src/memtest.c b/src/memtest.c index f45e2cf0de0d..f361d88e3e43 100644 --- a/src/memtest.c +++ b/src/memtest.c @@ -228,12 +228,21 @@ void memtest_compare_times(PORT_ULONG *m, size_t bytes, int pass, int times) { void memtest_test(size_t megabytes, int passes) { size_t bytes = megabytes * 1024 * 1024; +#ifdef _WIN32 + PORT_ULONG *m = VirtualAllocEx( + GetCurrentProcess(), + NULL, + bytes, + MEM_RESERVE | MEM_COMMIT | MEM_TOP_DOWN, + PAGE_READWRITE); +#else PORT_ULONG *m = malloc(bytes); +#endif int pass = 0; if (m == NULL) { - fprintf(stderr,"Unable to allocate %Iu megabytes: %s", - megabytes,strerror(errno)); WIN_PORT_FIX /* %zu -> %Iu */ + fprintf(stderr,"Unable to allocate %Iu megabytes: %s", WIN_PORT_FIX /* %zu -> %Iu */ + megabytes,strerror(errno)); exit(1); } while (pass != passes) { diff --git a/src/object.c b/src/object.c index 3f0cea171abe..2b21ebd2d096 100644 --- a/src/object.c +++ b/src/object.c @@ -140,7 +140,7 @@ robj *createStringObjectFromLongDouble(PORT_LONGDOUBLE value, int humanfriendly) * way that is "non surprising" for the user (that is, most small * decimal numbers will be represented in a way that when converted * back into a string are exactly the same as what the user typed.) */ - len = snprintf(buf,sizeof(buf),"%.15Lf",value); WIN_PORT_FIX /* %.17 -> %.15 on Windows the magic number is 15 */ + len = snprintf(buf,sizeof(buf),"%.15Lf",value); WIN_PORT_FIX /* %.17 -> %.15 on Windows the magic number is 15 */ /* Now remove trailing zeroes after the '.' */ if (strchr(buf,'.') != NULL) { char *p = buf+len-1; diff --git a/src/rdb.c b/src/rdb.c index f3fdacb7eeeb..76d2dcfaf18e 100644 --- a/src/rdb.c +++ b/src/rdb.c @@ -788,24 +788,6 @@ int rdbSave(char *filename) { return REDIS_ERR; } -#ifdef _WIN32 -int rdbSaveBackground(char *filename) { - PORT_LONGLONG start; - start = ustime(); - server.dirty_before_bgsave = server.dirty; - if (BeginForkOperation_Rdb(filename, &server, sizeof(server), &server.rdb_child_pid, dictGetHashFunctionSeed(), server.logfile)) { - server.stat_fork_time = ustime()-start; - server.rdb_child_type = REDIS_RDB_CHILD_TYPE_DISK; - updateDictResizePolicy(); - return REDIS_OK; - } else { - redisLog(REDIS_WARNING,"Can't save in background: fork: %s", strerror(errno)); - return REDIS_ERR; - } -} - -#else - int rdbSaveBackground(char *filename) { pid_t childpid; PORT_LONGLONG start; @@ -816,6 +798,9 @@ int rdbSaveBackground(char *filename) { server.lastbgsave_try = time(NULL); start = ustime(); +#ifdef _WIN32 + childpid = BeginForkOperation_Rdb(filename, &server, sizeof(server), dictGetHashFunctionSeed(), server.logfile); +#else if ((childpid = fork()) == 0) { int retval; @@ -834,6 +819,7 @@ int rdbSaveBackground(char *filename) { } exitFromChild((retval == REDIS_OK) ? 0 : 1); } else { +#endif /* Parent */ server.stat_fork_time = ustime()-start; server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */ @@ -850,10 +836,11 @@ int rdbSaveBackground(char *filename) { server.rdb_child_type = REDIS_RDB_CHILD_TYPE_DISK; updateDictResizePolicy(); return REDIS_OK; +#ifndef _WIN32 } +#endif return REDIS_OK; /* unreached */ } -#endif void rdbRemoveTempFile(pid_t childpid) { char tmpfile[256]; @@ -1482,7 +1469,9 @@ int rdbSaveToSlavesSockets(void) { /* Create the child process. */ start = ustime(); -#ifndef _WIN32 +#ifdef _WIN32 + childpid = BeginForkOperation_Socket(fds, numfds, clientids, pipefds[1], &server, sizeof(server), dictGetHashFunctionSeed(), server.logfile); +#else if ((childpid = fork()) == 0) { /* Child */ int retval; @@ -1549,12 +1538,6 @@ int rdbSaveToSlavesSockets(void) { zfree(clientids); exitFromChild((retval == REDIS_OK) ? 0 : 1); } else { -#else // #ifndef _WIN32 - if (!BeginForkOperation_Socket(fds, numfds, clientids, pipefds[1], &server, sizeof(server), &server.rdb_child_pid, dictGetHashFunctionSeed(), server.logfile)) { - redisLog(REDIS_WARNING,"Can't save in background: fork: %s", strerror(errno)); - return REDIS_ERR; - } else { - childpid = server.rdb_child_pid; #endif /* Parent */ zfree(clientids); /* Not used by parent. Free ASAP. */ @@ -1576,7 +1559,9 @@ int rdbSaveToSlavesSockets(void) { updateDictResizePolicy(); zfree(fds); return REDIS_OK; +#ifndef _WIN32 } +#endif return REDIS_OK; /* unreached */ } diff --git a/src/redis-check-dump.c b/src/redis-check-dump.c index 075e599f3bb3..5a238940654a 100644 --- a/src/redis-check-dump.c +++ b/src/redis-check-dump.c @@ -57,28 +57,29 @@ /* File maping used in redis-check-dump */ /* mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); */ void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset) { - HANDLE h; - void *data; + HANDLE h; + void *data; - (void)offset; + (void) offset; - if ((flags != MAP_SHARED) || (prot != PROT_READ)) { - /* Not supported in this port */ - return MAP_FAILED; + if ((flags != MAP_SHARED) || (prot != PROT_READ)) { + /* Not supported in this port */ + return MAP_FAILED; }; - h = CreateFileMapping((HANDLE)_get_osfhandle(fd), - NULL,PAGE_READONLY,0,0,NULL); - - if (!h) return MAP_FAILED; - - data = MapViewOfFileEx(h, FILE_MAP_READ,0,0,length,start); + h = CreateFileMapping((HANDLE) _get_osfhandle(fd), NULL, PAGE_READONLY, 0, 0, NULL); + if (!h) { + return MAP_FAILED; + } - CloseHandle(h); + data = MapViewOfFileEx(h, FILE_MAP_READ, 0, 0, length, start); + CloseHandle(h); - if (!data) return MAP_FAILED; + if (!data) { + return MAP_FAILED; + } - return data; + return data; } /* Unmap file mapping */ diff --git a/src/redis.c b/src/redis.c index 9bfc66c40d10..2939df42be39 100644 --- a/src/redis.c +++ b/src/redis.c @@ -29,6 +29,10 @@ #ifdef _WIN32 #include "win32_Interop\win32_util.h" +#include "Win32_Interop\Win32_FDAPI.h" +#include "Win32_Interop\Win32_ThreadControl.h" +#include +#define LOG_LOCAL0 0 #endif #include "redis.h" @@ -39,11 +43,7 @@ #include #include -#ifdef _WIN32 -#include -#define LOG_LOCAL0 0 -#include "redisLog.h" -#else +#ifndef _WIN32 #include #include #include @@ -60,10 +60,8 @@ #include #include #include +#ifndef _WIN32 #include - -#ifdef _WIN32 -#include "Win32_Interop\Win32_FDAPI.h" #endif /* Our shared "common" objects */ @@ -1148,10 +1146,10 @@ int serverCron(struct aeEventLoop *eventLoop, PORT_LONGLONG id, void *clientData if (!server.sentinel_mode) { run_with_period(5000) { redisLog(REDIS_VERBOSE, - "%Iu clients connected (%Iu slaves), %Iu bytes in use", + "%Iu clients connected (%Iu slaves), %Iu bytes in use", WIN_PORT_FIX /* %zu -> %Iu */ listLength(server.clients)-listLength(server.slaves), listLength(server.slaves), - zmalloc_used_memory()); WIN_PORT_FIX /* %zu -> %Iu */ + zmalloc_used_memory()); } } @@ -1172,19 +1170,23 @@ int serverCron(struct aeEventLoop *eventLoop, PORT_LONGLONG id, void *clientData /* Check if a background saving or AOF rewrite in progress terminated. */ if (server.rdb_child_pid != -1 || server.aof_child_pid != -1) { #ifdef _WIN32 - if (GetForkOperationStatus() == osCOMPLETE || GetForkOperationStatus() == osFAILED) { - int exitCode; - int bySignal; - bySignal = (int)(GetForkOperationStatus() == osFAILED); - redisLog(REDIS_WARNING, (bySignal ? "fork operation failed" : "fork operation complete")); - EndForkOperation(&exitCode); - if (server.rdb_child_pid != -1) { - backgroundSaveDoneHandler(exitCode, bySignal); - } else { - backgroundRewriteDoneHandler(exitCode, bySignal); - } - updateDictResizePolicy(); - } + if (GetForkOperationStatus() == osCOMPLETE || GetForkOperationStatus() == osFAILED) { + RequestSuspension(); + if (SuspensionCompleted()) { + int exitCode; + int bySignal; + bySignal = (int)(GetForkOperationStatus() == osFAILED); + redisLog(REDIS_WARNING, (bySignal ? "fork operation failed" : "fork operation complete")); + EndForkOperation(&exitCode); + ResumeFromSuspension(); + if (server.rdb_child_pid != -1) { + backgroundSaveDoneHandler(exitCode, bySignal); + } else { + backgroundRewriteDoneHandler(exitCode, bySignal); + } + updateDictResizePolicy(); + } + } #else int statloc; pid_t pid; @@ -1453,23 +1455,8 @@ void initServerConfig(void) { server.saveparams = NULL; server.loading = 0; server.logfile = zstrdup(REDIS_DEFAULT_LOGFILE); -#ifdef _WIN32 - // this is handled before redis_main() in Win32_QFork.cpp:::SetupLogging() - /* - if (RunningAsService()) { - server.syslog_enabled = 1; - server.syslog_ident = zstrdup(GetServiceName()); - } else { - server.syslog_ident = zstrdup(REDIS_DEFAULT_SYSLOG_IDENT); - server.syslog_enabled = REDIS_DEFAULT_SYSLOG_ENABLED; - } - setSyslogEnabled(server.syslog_enabled); - setSyslogIdent(server.syslog_ident); - */ -#else - server.syslog_enabled = REDIS_DEFAULT_SYSLOG_ENABLED; + server.syslog_enabled = REDIS_DEFAULT_SYSLOG_ENABLED; server.syslog_ident = zstrdup(REDIS_DEFAULT_SYSLOG_IDENT); -#endif server.syslog_facility = LOG_LOCAL0; server.daemonize = REDIS_DEFAULT_DAEMONIZE; server.aof_state = REDIS_AOF_OFF; @@ -2731,12 +2718,14 @@ sds genRedisInfoString(char *section) { "os:%s %s %s\r\n" "arch_bits:%d\r\n" "multiplexing_api:%s\r\n" +#ifndef _WIN32 "gcc_version:%d.%d.%d\r\n" +#endif "process_id:%ld\r\n" "run_id:%s\r\n" "tcp_port:%d\r\n" #ifdef _WIN32 - "uptime_in_seconds:%lld\r\n" /* BUGBUG: fix %lld */ + "uptime_in_seconds:%lld\r\n" "uptime_in_days:%lld\r\n" #else "uptime_in_seconds:%jd\r\n" @@ -2757,10 +2746,12 @@ sds genRedisInfoString(char *section) { #endif server.arch_bits, aeGetApiName(), +#ifndef _WIN32 #ifdef __GNUC__ __GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__, #else 0,0,0, +#endif #endif (PORT_LONG) getpid(), server.runid, @@ -2902,7 +2893,7 @@ sds genRedisInfoString(char *section) { "aof_current_size:%lld\r\n" "aof_base_size:%lld\r\n" "aof_pending_rewrite:%d\r\n" - "aof_buffer_length:%Iu\r\n" + "aof_buffer_length:%Iu\r\n" WIN_PORT_FIX /* %zu -> %Iu */ "aof_rewrite_buffer_length:%lu\r\n" "aof_pending_bio_fsync:%llu\r\n" "aof_delayed_fsync:%lu\r\n", @@ -2912,7 +2903,7 @@ sds genRedisInfoString(char *section) { sdslen(server.aof_buf), aofRewriteBufferSize(), bioPendingJobsOfType(REDIS_BIO_AOF_FSYNC), - server.aof_delayed_fsync); WIN_PORT_FIX /* %zu -> %Iu */ + server.aof_delayed_fsync); } if (server.loading) { @@ -3688,9 +3679,17 @@ void loadDataFromDisk(void) { } void redisOutOfMemoryHandler(size_t allocation_size) { - redisLog(REDIS_WARNING,"Out Of Memory allocating %Iu bytes!", - allocation_size); WIN_PORT_FIX /* %zu -> %Iu */ +#ifdef _WIN32 + bugReportStart(); + redisLog(REDIS_WARNING, "Out Of Memory allocating %Iu bytes.", /* %zu -> %Iu */ + allocation_size); + // Call abort() instead of forcing an access violation in redisPanic + abort(); +#else + redisLog(REDIS_WARNING,"Out Of Memory allocating %zu bytes!", + allocation_size); redisPanic("Redis aborting for OUT OF MEMORY"); +#endif } void redisSetProcTitle(char *title) { diff --git a/src/redis.h b/src/redis.h index 4f724ab6ac4d..9eb187fa7a9e 100644 --- a/src/redis.h +++ b/src/redis.h @@ -73,7 +73,7 @@ typedef PORT_LONGLONG mstime_t; /* millisecond time type. */ #include "latency.h" /* Latency monitor API */ #include "sparkline.h" /* ASII graphs API */ -#include "redisLog.h" /* moved logging for hiredis and RedisCli usage /* +#include "Win32_Interop/Win32_RedisLog.h" /* moved logging for hiredis and RedisCli usage /* /* Error codes */ #define REDIS_OK 0 @@ -94,7 +94,7 @@ typedef PORT_LONGLONG mstime_t; /* millisecond time type. */ #define REDIS_SHARED_INTEGERS 10000 #define REDIS_SHARED_BULKHDR_LEN 32 #ifdef _WIN32 -// see redisLog.h +// see Win32_RedisLog.h #else #define REDIS_MAX_LOGMSG_LEN 1024 /* Default maximum length of syslog messages */ #endif @@ -314,7 +314,7 @@ typedef PORT_LONGLONG mstime_t; /* millisecond time type. */ #define REDIS_SORTKEY_MAX 1024 #ifdef _WIN32 -// see redisLog.h +// see Win32_RedisLog.h #else /* Log levels */ #define REDIS_DEBUG 0 diff --git a/src/replication.c b/src/replication.c index f8b06285a840..e6110575221b 100644 --- a/src/replication.c +++ b/src/replication.c @@ -283,7 +283,7 @@ void replicationFeedMonitors(redisClient *c, list *monitors, int dictid, robj ** for (j = 0; j < argc; j++) { if (argv[j]->encoding == REDIS_ENCODING_INT) { - cmdrepr = sdscatprintf(cmdrepr, "\"%Id\"", (PORT_LONG) argv[j]->ptr); /* PORTABILITY FIX %ld -> %Id */ + cmdrepr = sdscatprintf(cmdrepr, "\"%Id\"", (PORT_LONG) argv[j]->ptr); WIN_PORT_FIX /* %ld -> %Id */ } else { cmdrepr = sdscatrepr(cmdrepr,(char*)argv[j]->ptr, sdslen(argv[j]->ptr)); @@ -1041,7 +1041,7 @@ void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) { "MASTER <-> SLAVE sync: receiving streamed RDB from master"); } else { usemark = 0; - server.repl_transfer_size = IF_WIN32(strtoll,strtol)(buf+1,NULL,10); + server.repl_transfer_size = IF_WIN32(strtoll,strtol)(buf+1,NULL,10); /* BUGBUG: verify for 32bit support */ redisLog(REDIS_NOTICE, "MASTER <-> SLAVE sync: receiving %lld bytes from master", (PORT_LONGLONG) server.repl_transfer_size); diff --git a/src/scripting.c b/src/scripting.c index ab5f959f6934..9cec41fac27e 100644 --- a/src/scripting.c +++ b/src/scripting.c @@ -612,11 +612,12 @@ void scriptingEnableGlobalsProtection(lua_State *lua) { /* strict.lua from: http://metalua.luaforge.net/src/lib/strict.lua.html. * Modified to be adapted to Redis. */ + s[j++]="local dbg=debug\n"; s[j++]="local mt = {}\n"; s[j++]="setmetatable(_G, mt)\n"; s[j++]="mt.__newindex = function (t, n, v)\n"; - s[j++]=" if debug.getinfo(2) then\n"; - s[j++]=" local w = debug.getinfo(2, \"S\").what\n"; + s[j++]=" if dbg.getinfo(2) then\n"; + s[j++]=" local w = dbg.getinfo(2, \"S\").what\n"; s[j++]=" if w ~= \"main\" and w ~= \"C\" then\n"; s[j++]=" error(\"Script attempted to create global variable '\"..tostring(n)..\"'\", 2)\n"; s[j++]=" end\n"; @@ -624,11 +625,12 @@ void scriptingEnableGlobalsProtection(lua_State *lua) { s[j++]=" rawset(t, n, v)\n"; s[j++]="end\n"; s[j++]="mt.__index = function (t, n)\n"; - s[j++]=" if debug.getinfo(2) and debug.getinfo(2, \"S\").what ~= \"C\" then\n"; + s[j++]=" if dbg.getinfo(2) and dbg.getinfo(2, \"S\").what ~= \"C\" then\n"; s[j++]=" error(\"Script attempted to access unexisting global variable '\"..tostring(n)..\"'\", 2)\n"; s[j++]=" end\n"; s[j++]=" return rawget(t, n)\n"; s[j++]="end\n"; + s[j++]="debug = nil\n"; s[j++]=NULL; for (j = 0; s[j] != NULL; j++) code = sdscatlen(code,s[j],strlen(s[j])); @@ -732,10 +734,11 @@ void scriptingInit(void) { * information about the caller, that's what makes sense from the point * of view of the user debugging a script. */ { - char *errh_func = "function __redis__err__handler(err)\n" - " local i = debug.getinfo(2,'nSl')\n" + char *errh_func = "local dbg = debug\n" + "function __redis__err__handler(err)\n" + " local i = dbg.getinfo(2,'nSl')\n" " if i and i.what == 'C' then\n" - " i = debug.getinfo(3,'nSl')\n" + " i = dbg.getinfo(3,'nSl')\n" " end\n" " if i then\n" " return i.source .. ':' .. i.currentline .. ': ' .. err\n" diff --git a/src/sentinel.c b/src/sentinel.c index 4c9d17373a41..9e7050ed4fd0 100644 --- a/src/sentinel.c +++ b/src/sentinel.c @@ -776,7 +776,7 @@ void sentinelRunPendingScripts(void) { CloseHandle( pi.hThread ); sentinel.running_scripts++; - sentinelEvent(REDIS_DEBUG, "+script-child", NULL, "%ld", (long) sj->pid); /* BUGBUG: fix %ld */ + sentinelEvent(REDIS_DEBUG, "+script-child", NULL, "%Id", (PORT_LONG) sj->pid); WIN_PORT_FIX /* %ld -> %Id */ } else { sentinelEvent(REDIS_WARNING,"-script-error",NULL, "%s %d %d", sj->argv[0], 99, 0); @@ -845,8 +845,8 @@ void sentinelCollectTerminatedScripts(void) { if(WaitForSingleObject(sj->hScriptProcess,0) == WAIT_OBJECT_0) { GetExitCodeProcess(sj->hScriptProcess,&exitCode); - sentinelEvent(REDIS_DEBUG,"-script-child",NULL,"%ld %d %d", - (long) sj->pid, exitCode, 0); /* BUGBUG: fix %ld */ + sentinelEvent(REDIS_DEBUG, "-script-child", NULL, "%Id %d %d", WIN_PORT_FIX /* %ld -> %Id*/ + (PORT_LONG) sj->pid, exitCode, 0); /* at this point the process ID may be recycled by Windows */ CloseHandle(sj->hScriptProcess); @@ -932,8 +932,8 @@ void sentinelKillTimedoutScripts(void) { if (sj->flags & SENTINEL_SCRIPT_RUNNING && (now - sj->start_time) > SENTINEL_SCRIPT_MAX_RUNTIME) { - sentinelEvent(REDIS_WARNING, "-script-timeout", NULL, "%s %ld", - sj->argv[0], (long) sj->pid); /* BUGBUG */ + sentinelEvent(REDIS_WARNING, "-script-timeout", NULL, "%s %Id", WIN_PORT_FIX /* %ld -> %Id*/ + sj->argv[0], (PORT_LONG) sj->pid); #ifdef _WIN32 TerminateProcess(sj->hScriptProcess,1); #else @@ -1607,16 +1607,16 @@ void rewriteConfigSentinelOption(struct rewriteConfigState *state) { /* sentinel down-after-milliseconds */ if (master->down_after_period != SENTINEL_DEFAULT_DOWN_AFTER) { line = sdscatprintf(sdsempty(), - "sentinel down-after-milliseconds %s %ld", - master->name, (long) master->down_after_period); /* BUGBUG */ + "sentinel down-after-milliseconds %s %Id", WIN_PORT_FIX /* %ld -> %Id*/ + master->name, (PORT_LONG) master->down_after_period); rewriteConfigRewriteLine(state,"sentinel",line,1); } /* sentinel failover-timeout */ if (master->failover_timeout != SENTINEL_DEFAULT_FAILOVER_TIMEOUT) { line = sdscatprintf(sdsempty(), - "sentinel failover-timeout %s %ld", - master->name, (long) master->failover_timeout); /* BUGBUG */ + "sentinel failover-timeout %s %Id", WIN_PORT_FIX /* %ld -> %Id*/ + master->name, (PORT_LONG) master->failover_timeout); rewriteConfigRewriteLine(state,"sentinel",line,1); } diff --git a/src/zmalloc.c b/src/zmalloc.c index 6a5dbce52427..35880a084d59 100644 --- a/src/zmalloc.c +++ b/src/zmalloc.c @@ -131,8 +131,8 @@ pthread_mutex_t used_memory_mutex = PTHREAD_MUTEX_INITIALIZER; #endif static void zmalloc_default_oom(size_t size) { - fprintf(stderr, "zmalloc: Out of memory trying to allocate %Iu bytes\n", - size); WIN_PORT_FIX /* %zu -> %Iu */ + fprintf(stderr, "zmalloc: Out of memory trying to allocate %Iu bytes\n", WIN_PORT_FIX /* %zu -> %Iu */ + size); fflush(stderr); abort(); } diff --git a/tests/integration/aof.tcl b/tests/integration/aof.tcl index f41a8603d49e..d352d2a4ad31 100644 --- a/tests/integration/aof.tcl +++ b/tests/integration/aof.tcl @@ -88,8 +88,9 @@ tags {"aof"} { test "Bad format: Server should have logged an error" { set pattern "*Bad file format reading the append only file*" set retry 10 + #WIN_PORT_FIX 'tail -n1' -> 'tail -1' while {$retry} { - set result [exec tail -n1 < [dict get $srv stdout]] + set result [exec tail -1 < [dict get $srv stdout]] if {[string match $pattern $result]} { break } @@ -113,8 +114,9 @@ tags {"aof"} { test "Unfinished MULTI: Server should have logged an error" { set pattern "*Unexpected end of file reading the append only file*" set retry 10 + #WIN_PORT_FIX 'tail -n1' -> 'tail -1' while {$retry} { - set result [exec tail -n1 < [dict get $srv stdout]] + set result [exec tail -1 < [dict get $srv stdout]] if {[string match $pattern $result]} { break } @@ -137,8 +139,9 @@ tags {"aof"} { test "Short read: Server should have logged an error" { set pattern "*Unexpected end of file reading the append only file*" set retry 10 + #WIN_PORT_FIX 'tail -n1' -> 'tail -1' while {$retry} { - set result [exec tail -n1 < [dict get $srv stdout]] + set result [exec tail -1 < [dict get $srv stdout]] if {[string match $pattern $result]} { break } diff --git a/tests/unit/aofrw.tcl b/tests/unit/aofrw.tcl index a2d74168f3ee..4acbdcd550a8 100644 --- a/tests/unit/aofrw.tcl +++ b/tests/unit/aofrw.tcl @@ -69,8 +69,9 @@ start_server {tags {"aofrw"}} { r bgrewriteaof r config set appendonly no r exec + #WIN_PORT_FIX 'tail -n5' -> 'tail -5' wait_for_condition 50 100 { - [string match {*Killing*AOF*child*} [exec tail -n5 < [srv 0 stdout]]] + [string match {*Killing*AOF*child*} [exec tail -5 < [srv 0 stdout]]] } else { fail "Can't find 'Killing AOF child' into recent logs" }