提交 62cc0e32 编写于 作者: J Jonathan Pickett

Merge branch '2_6_14_rebase' into 2.8.4

Conflicts:
	00-RELEASENOTES
	deps/hiredis/hiredis.c
	deps/hiredis/sds.c
	deps/jemalloc/ChangeLog
	deps/jemalloc/Makefile.in
	deps/jemalloc/VERSION
	deps/jemalloc/configure
	deps/jemalloc/configure.ac
	deps/jemalloc/doc/jemalloc.3
	deps/jemalloc/doc/jemalloc.html
	deps/jemalloc/doc/jemalloc.xml.in
	deps/jemalloc/include/jemalloc/internal/arena.h
	deps/jemalloc/include/jemalloc/internal/chunk.h
	deps/jemalloc/include/jemalloc/internal/chunk_dss.h
	deps/jemalloc/include/jemalloc/internal/chunk_mmap.h
	deps/jemalloc/include/jemalloc/internal/ctl.h
	deps/jemalloc/include/jemalloc/internal/extent.h
	deps/jemalloc/include/jemalloc/internal/huge.h
	deps/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in
	deps/jemalloc/include/jemalloc/internal/private_namespace.h
	deps/jemalloc/include/jemalloc/internal/prof.h
	deps/jemalloc/include/jemalloc/internal/rtree.h
	deps/jemalloc/include/jemalloc/jemalloc.h.in
	deps/jemalloc/include/jemalloc/jemalloc_defs.h.in
	deps/jemalloc/src/arena.c
	deps/jemalloc/src/base.c
	deps/jemalloc/src/chunk.c
	deps/jemalloc/src/chunk_dss.c
	deps/jemalloc/src/chunk_mmap.c
	deps/jemalloc/src/ctl.c
	deps/jemalloc/src/huge.c
	deps/jemalloc/src/jemalloc.c
	deps/jemalloc/src/mutex.c
	deps/jemalloc/src/prof.c
	deps/jemalloc/src/rtree.c
	deps/jemalloc/src/stats.c
	deps/jemalloc/src/tcache.c
	deps/jemalloc/src/util.c
	deps/jemalloc/src/zone.c
	deps/jemalloc/test/thread_arena.c
	deps/linenoise/linenoise.c
	redis.conf
	src/Makefile.dep
	src/ae.c
	src/anet.c
	src/anet.h
	src/aof.c
	src/bitops.c
	src/config.c
	src/config.h
	src/db.c
	src/debug.c
	src/dict.c
	src/memtest.c
	src/mkreleasehdr.sh
	src/networking.c
	src/object.c
	src/rdb.c
	src/redis-benchmark.c
	src/redis-cli.c
	src/redis.c
	src/redis.h
	src/release.c
	src/replication.c
	src/rio.c
	src/rio.h
	src/scripting.c
	src/sds.c
	src/sentinel.c
	src/t_list.c
	src/t_string.c
	src/t_zset.c
	src/version.h
	src/zmalloc.c
	tests/assets/default.conf
	tests/integration/rdb.tcl
	tests/test_helper.tcl
	tests/unit/basic.tcl
	tests/unit/expire.tcl
	tests/unit/obuf-limits.tcl
	tests/unit/pubsub.tcl
	tests/unit/scripting.tcl

Still having problems with BLPOP
......@@ -25,3 +25,42 @@ deps/lua/src/liblua.a
.make-*
.prerequisites
*.dSYM
*.user
*.exe
*.sdf
*.suo
msvs/Debug/
msvs/Release/
msvs/RedisBenchmark/Debug/
msvs/RedisBenchmark/Release/
msvs/RedisBenchmark/x64/
msvs/RedisCheckAof/Debug/
msvs/RedisCheckAof/Release/
msvs/RedisCheckAof/x64/
msvs/RedisCheckDump/Debug/
msvs/RedisCheckDump/Release/
msvs/RedisCheckDump/x64/
msvs/RedisCli/Debug/
msvs/RedisCli/Release/
msvs/RedisCli/x64/
msvs/hiredis/Debug/
msvs/hiredis/Release/
msvs/hiredis/x64/
msvs/lua/lua/Debug/
msvs/lua/lua/Release/
msvs/lua/lua/x64/
msvs/x64/
msvs/ipch
msvs/RedisServer.opensdf
!msvs/RedisWaInst/bin/*
!msvs/RedisWaInst/bin/Inst4WA/*
!msvs/RedisWaInst/bin/RedisPkgBin/*
msvs/RedisWAInst/src/RedisDeployCmdlets/bin/
msvs/RedisWAInst/src/RedisDeployCmdlets/obj/
msvs/RedisWAInst/src/RedisInstBin/
msvs/RedisWAInst/src/RedisInstWA/app.config
msvs/RedisWAInst/src/RedisInstWA/bin/
msvs/RedisWAInst/src/RedisInstWA/obj/
msvs/RedisWAInst/src/RedisServer/bin/
msvs/RedisWAInst/src/RedisServer/obj/
......@@ -14,164 +14,189 @@ HIGH: There is a critical bug that may affect a subset of users. Upgrade!
CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.
--------------------------------------------------------------------------------
--[ Redis 2.8.4 ] Release date: 13 Jan 2014
# UPGRADE URGENCY: MODERATE for Redis and Sentinel.
* [FIX] Makefile compatibility with non common make variants improved.
* [FIX] SDIFF crash in very unlikely to trigger state fixed.
* [FIX] Config rewriting fixed: don't wipe options unknown to the rewrite
process.
* [FIX] Set TCP port to 0 works again to disable TCP networking.
* [FIX] Fixed replication with old Redis instances as masters by not
sending REPLCONF ACK to them.
* [FIX] Fix keyspace notifications rewrite and CONFIG GET output.
* [FIX] Fix RESTORE TTL handling in 32 bit systems (32 bit overflow).
* [NEW] Sentinel now has a run time configuration API.
* [NEW] Log when we lost connection with master or slave.
* [NEW] When instance is turned from slave to master now inherits the
old master replication offset when possible. This improves the
Sentinel failover procedure.
--[ Redis 2.8.3 ] Release date: 11 Dec 2013
# UPGRADE URGENCY: MODERATE for Redis, HIGH for Sentinel.
* [FIX] Sentinel instance role sampling fixed, the system is now more
reliable during failover and when reconfiguring instances with
non matching configuration.
* [FIX] Inline requests are now handled even when terminated with just LF.
* [FIX] Replication timeout handling greatly improved, now the slave is able
to ping the master while removing the old data from memory, and while
loading the new RDB file. This avoid false timeouts sensed by
masters.
* [FIX] Fixed a replication bug involving 32 bit instances and big datasets
hard to compress that resulted into more than 2GB of RDB file sent.
* [FIX] Return error for inline requests with unbalanced quotes.
* [FIX] Publish the slave replication offset even when disconnected from the
master if there is still a cached master instance.
--[ Redis 2.8.2 ] Release date: 2 Dec 2013
# UPGRADE URGENCY: MODERATE for both Redis and Sentinel.
* [FIX] Sentinel better desynchronization to avoid split-brain elections
where no Sentinel managed to get elected.
* [FIX] Stop accepting writes on "MISCONF" error only if master, not slave.
* [FIX] Reply to PING with an error on "MISCONF" errors.
--[ Redis 2.8.1 ] Release date: 25 Nov 2013
# UPGRADE URGENCY: LOW for Redis, CRITICAL for Senitnel. You don't need to
upgrade your Redis instances but it is highly recommended
to upgrade and restart all the Sentinel processes.
* [FIX] Fixed a bug in "new Sentinel" config propagation.
* [FIX] Fixed a false positive in Redis tests.
--[ Redis 2.8.0 ] Release date: 22 Nov 2013
# UPGRADE URGENCY: LOW, unless you want to upgrade to new Sentinel code.
* [FIX] Fixed an error in rdbWriteRaw() that should have no practical impact.
* [NEW] Log the new master when SLAVEOF command is used.
* [NEW] Sentinel code synchronized with the unstable branch, the new Sentinel
is a reimplementation that uses more reliable algorithms.
--[ Redis 2.8 Release Candidate 6 (2.7.106) ] Release date: 6 Nov 2013
This is the 6th release candidate of Redis 2.8 (official version is 2.7.106).
# UPGRADE URGENCY: LOW, only new features back ported, no fixes.
* [NEW] SCAN, SSCAN, HSCAN, ZSCAN commands.
--[ Redis 2.8 Release Candidate 5 (2.7.105) ] Release date: 9 Oct 2013
This is the 5th release candidate of Redis 2.8 (official version is 2.7.105).
Important bugs fixed inside.
# UPGRADE URGENCY: HIGH because of many non critical replication bugs fixed.
* [FIX] redis-cli: don't crash with --bigkeys when the key no longer exist.
* [FIX] Allow AUTH / PING when disconnected from slave and serve-stale-data is no.
* [FIX] PSYNC: safer handling of PSYNC requests with offsets in the future.
* [FIX] Replication: Fix master timeout detection.
* [FIX] Replication: Correctly install the write handler after successful PSYNC.
--[ Redis 2.8 Release Candidate 4 (2.7.104) ] Release date: 30 Aug 2013
This is the fourth release candidate of Redis 2.8 (official version is 2.7.104).
Important bugs fixed inside.
# UPGRADE URGENCY: HIGH because of the EVAL memory leak.
* [FIX] Fixed a serious EVAL memory leak in the Lua stack.
* [FIX] Fixed server startup when no IPv6 address exists in any interface.
* [FIX] Send MISCONFIG error when BGSAVE fails because can't fork.
* [FIX] Memory efficiency with large (> a few kbytes) values improved considerably.
* [NEW] DEBUG SDSLEN for sds memory debugging.
--[ Redis 2.8 Release Candidate 3 (2.7.103) ] Release date: 19 Aug 2013
This is the third release candidate of Redis 2.8 (official version is 2.7.103).
Important bugs fixed inside.
# UPGRADE URGENCY: HIGH
* [FIX] Improved expired keys collection algorithm. Even under heavy load keys
to be expired can't accumulate because of lack of CPU time.
* [FIX] Replication speed regression fixed (issue #1238).
* [FIX] Fixed an hard to trigger PSYNC bug.
* [FIX] Fixed Issue #1240, ZUNIONSTORE could lead to wrong result.
* [NEW] Add per-db average TTL information in INFO output.
* [NEW] redis-benchmark improvements.
* [NEW] dict.c API wrong usage detection.
--[ Redis 2.8 Release Candidate 2 (2.7.102) ] Release date: 30 Jul 2013
This is the second release candidate of Redis 2.8 (official version is 2.7.102).
Important bugs fixed inside.
# UPGRADE URGENCY: HIGH
* [FIX] Fixed a critical replication bug, see issue #1221.
* [NEW] The new inline protocol now accepts quoted strings like, for example
you can now type in a telnet session: set 'foo bar' "hello world\n".
--[ Redis 2.8 Release Candidate 1 (2.7.101) ] Release date: 18 Jul 2013
This is the first release candidate of Redis 2.8 (official version is 2.7.101).
The following is a list of improvements in Redis 2.8, compared to Redis 2.6.
* [NEW] Slaves are now able to partially resynchronize with the master, so most
of the times a full resynchronization with the RDB creation in the master
side is not needed when the master-slave link is disconnected for a short
amount of time.
* [NEW] Experimental IPv6 support.
* [NEW] Slaves explicitly ping masters now, a master is able to detect a timed out
slave independently.
* [NEW] Masters can stop accepting writes if not enough slaves with a given
maximum latency are connected.
* [NEW] Keyspace changes notifications via Pub/Sub.
* [NEW] CONFIG SET maxclients is now available.
* [NEW] Ability to bind multiple IP addresses.
* [NEW] Set process names so that you can recognize, in the "ps" command output,
the listening port of an instance, or if it is a saving child.
* [NEW] Automatic memory check on crash.
* [NEW] CONFIG REWRITE is able to materialize the changes in the configuration
operated using CONFIG SET into the redis.conf file.
* [NEW] More NetBSD friendly code base.
* [NEW] PUBSUB command for Pub/Sub introspection capabilities.
* [NEW] EVALSHA can now be replicated as such, without requiring to be expanded
to a full EVAL for the replication link.
* [NEW] Better Lua scripts error reporting.
* [NEW] SDIFF performance improved.
* [FIX] A number of bugfixes.
Migrating from 2.6 to 2.8
---[ Redis 2.6.0 ]
* [BUGFIX] Allow AUTH when server is in -BUSY state because of a slow script.
* [BUGFIX] MULTI/EXEC flow now makes sense when observed in MONITOR
* [BUGFIX] SCRIPT KILL now uses different error prefixes for different errors.
* [BUGFIX] Default memory limit for 32bit archs lowered from 3.5 to 3 GB.
* [BUGFIX] redis-check-dump is now compatible with RDB files generated by 2.6.
* [IMPROVED] New field in INFO: slave_read_only.
---[ Redis 2.5.14 (2.6 Release Candidate 8) ]
* [BUGFIX] Fixed compilation on FreeBSD.
* [IMPROVED] SRANDMEMBER <count> that returns multiple random elements.
* [IMPROVED] Sentinel backported to 2.6. It will be taken in sync with 2.8.
* [IMPROVED] Helper function for scripting to return errors and status replies.
* [IMPROVED] SORT by nosort [ASC|DESC] uses sorted set elements ordering.
* [BUGFIX] Better resistence to system clock skew.
* [IMPROVED] Warn the user when the configured maxmemory seems odd.
* [BUGFIX] Hashing function is now murmurhash2 for security purposes.
* [IMPROVED] Install script no longer uses a template but redis.conf itself.
---[ Redis 2.5.13 (2.6 Release Candidate 7) ]
UPGRADE URGENCY: HIGH
* [BUGFIX] Theoretical bug in ziplist fixed.
* [BUGFIX] Better out of memory handling (Log produced in log file).
* [BUGFIX] Incrementally flush RDB file on slave side while performing the
first synchronization with the master. This makes Redis less
blocking in environments where disk I/O is slow.
* [BUGFIX] Don't crash with Lua's redis.call() without arguments.
* [BUGFIX] Don't crash after a big number of Lua calls on 32 bit systems
because of a failed assertion.
* [BUGFIX] Fix SORT behaviour when called from scripting.
* [BUGFIX] Adjust slave PING period accordingly to REDIS_HZ define.
* [BUGFIX] BITCOUNT: fix crash on overflowing arguments.
* [BUGFIX] Return an error when SELECT argument is not an integer.
* [BUGFIX] Blocking operations on lists were completely reimplemented for
correctness. Now blocking list ops and pushes originated from
Lua scripts will play well together and will be replicated
and transmitted to the AOF correctly.
* [IMPROVED] Send async PING before starting replication to avoid blocking if
master allows us to connect but it is actually not able to reply.
* [IMPROVED] Support slave-priority for Redis Sentinel.
* [IMPROVED] Hiredis library updated.
---[ Redis 2.5.12 (2.6 Release Candidate 6) ]
UPGRADE URGENCY: MODERATE.
* [BUGFIX] Fixed a timing attack on AUTH (Issue #560).
* [BUGFIX] Don't assume that "char" is signed.
* [BUGFIX] Check that we have connection before enabling pipe mode.
* [BUGFIX] Use the optimized version of the function to convert a double to
its string representation. Compilation was disabled because of
a typo in the #if statement.
* [IMPROVED} REPLCONF internal command introduced, now INFO shows slaves with
correct port numbers. This makes 2.5.12 Redis Sentinel compatible.
* [IMPROVED] Truncate short write from the AOF for a cleaner restart. On short
writes (for instance out of space) Redis will now try to remove
the half-written data so that the next restart will work without
the need for the "redis-check-aof" utility.
* [IMPROVED] New in INFO: aof_last_bgrewrite_status
* [IMPROVED] Allow Pub/Sub in contexts where other commands are blocked.
* [BUGFIX] mark fd as writable when EPOLLERR or EPOLLHUP is returned by
epoll_wait.
---[ Redis 2.5.11 (2.6 Release Candidate 5) ]
UPGRADE URGENCY: HIGH.
* [BUGFIX] Fixed Hash corruption when loading an RDB file generated by
previous versions of Redis that encoded hashes using
a different ziplist encoding format for small integers.
All the fileds that are integers in the range 0-255 may not
be recognized, or duplicated un updates, causing a crash
when the ziplist is converted to a real hash. (Issue #547).
* [BUGFIX] Fixed the count of memory used by output buffers in the
setDeferredMultiBulkLength() function.
---[ Redis 2.5.10 (2.6 Release Candidate 4) ]
UPGRADE URGENCY: HIGH.
* [BUGFIX] Allow PREFIX to be overwritten on "make install".
* [BUGFIX] Run the test with just one client if the computer is slow.
* [BUGFIX] Event port support in our event driven libray.
* [BUGFIX] Jemalloc updated to 3.0.0. This fixes a possibly AOF rewrite issue.
See https://github.com/antirez/redis/issues/504 for info.
* [BUGFIX] Fixed issue #516: ZINTERSTORE / ZUNIONSTORE with mixed sets/zsets.
* [BUGFIX] Set fd to writable when poll(2) detects POLLERR or POLLHUP event.
* [BUGFIX] Fixed RESTORE hash failure (Issue #532).
* [IMPROVED] Allow an AOF rewrite buffer > 2GB (Related to issue #504).
* [IMPROVED] Server cron function frequency is now configurable (REDIS_HZ).
* [IMPROVED] Better, less blocking expired keys collection algorithm.
* [FEATURE] New commands: BITOP and BITCOUNT.
* [FEATURE] redis-cli --pipe for mass import.
What's new in Redis 2.5.9 (aka 2.6 Release Candidate 3)
=======================================================
UPGRADE URGENCY: critical, upgrade ASAP.
* [BUGFIX] Fix for issue #500 (https://github.com/antirez/redis/pull/500).
Redis 2.6-RC1 and RC2 may corrupt ziplist-encoded sorted sets
produced by Redis 2.4.x.
* [BUGFIX] Fixed several bugs in init.d script.
* [BUGFIX] syncio.c functions modified for speed and correctness. On osx
(and possibly other BSD-based systems) the slave would block on
replication to send the SYNC command when the master was not
available. This is fixed now, but was not affecting Linux installs.
* Now when slave-serve-stale-data is set to yes and the master is down, instead
of reporting a generic error Redis replies with -MASTERDOWN.
What's new in Redis 2.5.8 (aka 2.6 Release Candidate 2)
=======================================================
UPGRADE URGENCY: high for all the users of the KEYS command, otherwise low.
* [BUGFIX] Fix for KEYS command: if the DB contains keys with expires the KEYS
command may return the wrong output, having duplicated or missing
keys. See issue #487 and #488 on github for details.
What's new in Redis 2.5.7 (aka 2.6 Release Candidate 1)
=======================================================
UPGRADE URGENCY: upgrade not recommended because this is an RC release.
* This is the first release candidate for Redis 2.6. We are not aware of
bugs, but part of this code is young and was never tested in production
environments, so handle with care.
An overview of new features and changes in Redis 2.6.x
======================================================
* Server side Lua scripting, see http://redis.io/commands/eval
* Virtual Memory removed (was deprecated in 2.4)
* Hardcoded limits about max number of clients removed.
* AOF low level semantics is generally more sane, and especially when used
in slaves.
* Milliseconds resolution expires, also added new commands with milliseconds
precision (PEXPIRE, PTTL, ...).
* Better memory usage for "small" lists, ziplists and hashes when fields or
values contain small integers.
* Read only slaves.
* New bit opeations: BITCOUNT and BITOP commands.
* Clients max output buffer soft and hard limits. You can specifiy different
limits for different classes of clients (normal,pubsub,slave).
* More incremental (less blocking) expired keys collection algorithm, in
practical terms this means that Redis is more responsive when a very
big number of keys expire about at the same time.
* AOF is now able to rewrite aggregate data types using variadic commands,
often producing an AOF that is faster to save, load, and is smaller in size.
* Every redis.conf directive is now accepted as a command line option for the
redis-server binary, with the same name and number of arguments.
* Hash table seed randomization for protection against collisions attacks.
* Performances improved when writing large objects to Redis.
* Integrated memory test, see redis-server --test-memory.
* INCRBYFLOAT and HINCRBYFLOAT commands.
* New DUMP, RESTORE, MIGRATE commands (back ported from Redis Cluster to 2.6).
* CRC64 checksump in RDB files.
* Better MONITOR output and behavior (now commands are logged before execution).
* "Software Watchdog" feature to debug latency issues.
* Significant parts of the core refactored or rewritten. New internal APIs
and core changes allowed to develop Redis Cluster on top of the new code,
however for 2.6 all the cluster code was removed, and will be released with
Redis 3.0 when it is more complete and stable.
* Redis ASCII art logo added at startup.
* Crash report on memory violation or failed asserts improved significantly
to make debugging of hard to catch bugs simpler.
* redis-benchmark improvements: ability to run selected tests,
CSV output, faster, better help.
* redis-cli improvements: --eval for comfortable development of Lua scripts.
* SHUTDOWN now supports two optional arguments: "SAVE" and "NOSAVE".
* INFO output split into sections, the command is now able to just show
pecific sections.
* New statistics about how many time a command was called, and how much
execution time it used (INFO commandstats).
* More predictable SORT behavior in edge cases.
* Better support for big endian and *BSD systems.
* Build system improved.
Migrating from 2.4 to 2.6
=========================
Redis 2.6 is mostly a strict subset of 2.8. However there are a few things
......
Redis on Windows 2.6 prototype
===
## What's new in this release
- This is a port for Windows based on Redis 2.6. The latest version merged in 2.6.12.
- The port is similar to the port of Redis 2.4, including the same background saving technology.
- There is support for x64 version as well as 32 bit versions.
- For the 64 bit version, there is a limit of 2^32 objects in a structure, and a max length of 2^32 for any object
- Version number now 2.6.8-pre2 to indicate prerelease and to enable changing
- Version 2.6.8-pre2 fixes several failures that existed in 2.6.8-pre1. Most of these were related to handling opening and closing of non-blocking sockets.
- The unit/protocol desync test is updated to use nonblocking socket and now works on Windows
- The binaries (unsigned) have been moved to the root to make them easier to find. Previously they were under msvs.
- Signed binaries can be downloaded using Nuget.
##Acknowledgements
Special thanks to Dušan Majkic (https://github.com/dmajkic, https://github.com/dmajkic/redis/) for his project on GitHub that gave us the opportunity to quickly learn some on the intricacies of Redis code. His project also helped us to build our prototype quickly.
## Repo branches
- 2.6: This is the branch for the Windows Redis port based on Redis 2.6.
- 2.4: This branch has the Windows Redis port based on Redis 2.4.
## How to build Redis using Visual Studio
You can use the free Express Edition available at http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express.
- Open the solution file msvs\redisserver.sln in Visual Studio 10, select platform (win32 or x64) and build.
This should create the following executables in the msvs\$(Configuration) folder:
- redis-server.exe
- redis-benchmark.exe
- redis-cli.exe
- redis-check-dump.exe
- redis-check-aof.exe
For your convenience all binaries are be available in the msvs/bin/release|debug directories.
## RedisWatcher
So far the RedisWatcher is not carried over to 2.6. However this should not be affected by the Redis version, and the code in the 2.4 branch should work with the Redis 2.6 binaries.
## RedisWAInst
So far the RedisWAInst is not carried over to 2.6. However this should not be affected by the Redis version, and the code in the 2.4 branch should work with the Redis 2.6 binaries.
## Release Notes
The branch has been renamed from 2.6_alpha to 2.6 to indicate that the test pass has been completed.
This is a release version of the software.
To run the Redis test suite requires some manual work:
- The tests assume that the binaries are in the src folder, so you need to copy the binaries from the msvs folder to src.
- The tests make use of TCL. This must be installed separately.
- To run the tests you need to have a Unix shell on your machine. To execute the tests, run the following command: `tclsh8.5.exe tests/test_helper.tcl`.
If a Unix shell is not installed you may see the following error message: "couldn't execute "cat": no such file or directory".
## Known issues
None.
!release
!debug
!release/*
!debug/*
......@@ -32,7 +32,9 @@
#include "fmacros.h"
#include <stdlib.h>
#include <string.h>
#ifndef _WIN32
#include <strings.h>
#endif
#include <assert.h>
#include <ctype.h>
#include <errno.h>
......@@ -40,6 +42,9 @@
#include "net.h"
#include "dict.c"
#include "sds.h"
#ifdef _WIN32
#include "../../src/win32_Interop/win32fixes.h"
#endif
#define _EL_ADD_READ(ctx) do { \
if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \
......@@ -57,23 +62,28 @@
if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \
} while(0);
#ifdef _WIN32
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#endif
/* Forward declaration of function in hiredis.c */
void __redisAppendCommand(redisContext *c, char *cmd, size_t len);
/* Functions managing dictionary of callbacks for pub/sub. */
static unsigned int callbackHash(const void *key) {
return dictGenHashFunction((unsigned char*)key,sdslen((char*)key));
return dictGenHashFunction((unsigned char*)key,(int)sdslen((char*)key));
}
static void *callbackValDup(void *privdata, const void *src) {
((void) privdata);
redisCallback *dup = malloc(sizeof(*dup));
((void) privdata);
memcpy(dup,src,sizeof(*dup));
return dup;
}
static int callbackKeyCompare(void *privdata, const void *key1, const void *key2) {
int l1, l2;
size_t l1, l2;
((void) privdata);
l1 = sdslen((sds)key1);
......@@ -141,12 +151,26 @@ static void __redisAsyncCopyError(redisAsyncContext *ac) {
ac->errstr = c->errstr;
}
#ifdef WIN32_IOCP
redisAsyncContext *redisAsyncConnect(const char *ip, int port) {
struct sockaddr_in sa;
redisContext *c = redisPreConnectNonBlock(ip, port, &sa);
redisAsyncContext *ac = redisAsyncInitialize(c);
if (aeWinSocketConnect(c->fd, (struct sockaddr *)&sa, sizeof(sa)) != 0) {
c->err = errno;
strerror_r(errno,c->errstr,sizeof(c->errstr));
}
__redisAsyncCopyError(ac);
return ac;
}
#else
redisAsyncContext *redisAsyncConnect(const char *ip, int port) {
redisContext *c = redisConnectNonBlock(ip,port);
redisAsyncContext *ac = redisAsyncInitialize(c);
__redisAsyncCopyError(ac);
return ac;
}
#endif
redisAsyncContext *redisAsyncConnectUnix(const char *path) {
redisContext *c = redisConnectUnixNonBlock(path);
......@@ -442,7 +466,7 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
static int __redisAsyncHandleConnect(redisAsyncContext *ac) {
redisContext *c = &(ac->c);
if (redisCheckSocketError(c,c->fd) == REDIS_ERR) {
if (redisCheckSocketError(c,(int)c->fd) == REDIS_ERR) {
/* Try again later when connect(2) is still in progress. */
if (errno == EINPROGRESS)
return REDIS_OK;
......@@ -509,6 +533,46 @@ void redisAsyncHandleWrite(redisAsyncContext *ac) {
}
}
#ifdef _WIN32
/* The redisAsyncHandleWrite is split into a Prep and Complete routines
To allow using a write routine suitable for async behavior.
For Windows this will use IOCP on write. */
int redisAsyncHandleWritePrep(redisAsyncContext *ac) {
redisContext *c = &(ac->c);
if (!(c->flags & REDIS_CONNECTED)) {
/* Abort connect was not successful. */
if (__redisAsyncHandleConnect(ac) != REDIS_OK)
return REDIS_ERR;
/* Try again later when the context is still not connected. */
if (!(c->flags & REDIS_CONNECTED))
return REDIS_ERR;
}
return REDIS_OK;
}
int redisAsyncHandleWriteComplete(redisAsyncContext *ac, int written) {
redisContext *c = &(ac->c);
int done = 0;
int rc;
rc = redisBufferWriteDone(c, written, &done);
if (rc == REDIS_ERR) {
__redisAsyncDisconnect(ac);
} else {
/* Continue writing when not done, stop writing otherwise */
if (!done)
_EL_ADD_WRITE(ac);
else
_EL_DEL_WRITE(ac);
/* Always schedule reads after writes */
_EL_ADD_READ(ac);
}
return REDIS_OK;
}
#endif
/* Sets a pointer to the first argument and its length starting at p. Returns
* the number of bytes to skip to get to the following argument. */
static char *nextArgument(char *start, char **str, size_t *len) {
......
......@@ -111,6 +111,10 @@ void redisAsyncFree(redisAsyncContext *ac);
/* Handle read/write events */
void redisAsyncHandleRead(redisAsyncContext *ac);
void redisAsyncHandleWrite(redisAsyncContext *ac);
#ifdef _WIN32
int redisAsyncHandleWritePrep(redisAsyncContext *ac);
int redisAsyncHandleWriteComplete(redisAsyncContext *ac, int written);
#endif
/* Command functions for an async context. Write the command to the
* output buffer and register the provided callback. */
......
......@@ -42,7 +42,11 @@
/* -------------------------- private prototypes ---------------------------- */
static int _dictExpandIfNeeded(dict *ht);
#ifdef _WIN32
static size_t _dictNextPower(size_t size);
#else
static unsigned long _dictNextPower(unsigned long size);
#endif
static int _dictKeyIndex(dict *ht, const void *key);
static int _dictInit(dict *ht, dictType *type, void *privDataPtr);
......@@ -85,6 +89,53 @@ static int _dictInit(dict *ht, dictType *type, void *privDataPtr) {
}
/* Expand or create the hashtable */
#ifdef _WIN32
static int dictExpand(dict *ht, size_t size) {
dict n; /* the new hashtable */
size_t realsize = _dictNextPower(size), i;
/* the size is invalid if it is smaller than the number of
* elements already inside the hashtable */
if (ht->used > size)
return DICT_ERR;
_dictInit(&n, ht->type, ht->privdata);
n.size = realsize;
n.sizemask = realsize-1;
n.table = calloc(realsize,sizeof(dictEntry*));
/* Copy all the elements from the old to the new table:
* note that if the old hash table is empty ht->size is zero,
* so dictExpand just creates an hash table. */
n.used = ht->used;
for (i = 0; i < ht->size && ht->used > 0; i++) {
dictEntry *he, *nextHe;
if (ht->table[i] == NULL) continue;
/* For each hash entry on this slot... */
he = ht->table[i];
while(he) {
unsigned int h;
nextHe = he->next;
/* Get the new element index */
h = dictHashKey(ht, he->key) & n.sizemask;
he->next = n.table[h];
n.table[h] = he;
ht->used--;
/* Pass to the next element */
he = nextHe;
}
}
assert(ht->used == 0);
free(ht->table);
/* Remap the new hashtable in the old */
*ht = n;
return DICT_OK;
}
#else
static int dictExpand(dict *ht, unsigned long size) {
dict n; /* the new hashtable */
unsigned long realsize = _dictNextPower(size), i;
......@@ -130,6 +181,7 @@ static int dictExpand(dict *ht, unsigned long size) {
*ht = n;
return DICT_OK;
}
#endif
/* Add an element to the target hash table */
static int dictAdd(dict *ht, void *key, void *val) {
......@@ -303,6 +355,18 @@ static int _dictExpandIfNeeded(dict *ht) {
}
/* Our hash table capability is a power of two */
#ifdef _WIN32
static size_t _dictNextPower(size_t size) {
size_t i = DICT_HT_INITIAL_SIZE;
if (size >= LONG_MAX) return LONG_MAX;
while(1) {
if (i >= size)
return i;
i *= 2;
}
}
#else
static unsigned long _dictNextPower(unsigned long size) {
unsigned long i = DICT_HT_INITIAL_SIZE;
......@@ -313,6 +377,7 @@ static unsigned long _dictNextPower(unsigned long size) {
i *= 2;
}
}
#endif
/* Returns the index of a free slot that can be populated with
* an hash entry for the given 'key'.
......
......@@ -60,9 +60,15 @@ typedef struct dictType {
typedef struct dict {
dictEntry **table;
dictType *type;
#ifdef _WIN32
size_t size;
size_t sizemask;
size_t used;
#else
unsigned long size;
unsigned long sizemask;
unsigned long used;
#endif
void *privdata;
} dict;
......@@ -113,7 +119,11 @@ typedef struct dictIterator {
/* API */
static unsigned int dictGenHashFunction(const unsigned char *buf, int len);
static dict *dictCreate(dictType *type, void *privDataPtr);
#ifdef _WIN32
static int dictExpand(dict *ht, size_t size);
#else
static int dictExpand(dict *ht, unsigned long size);
#endif
static int dictAdd(dict *ht, void *key, void *val);
static int dictReplace(dict *ht, void *key, void *val);
static int dictDelete(dict *ht, const void *key);
......
......@@ -32,7 +32,9 @@
#include "fmacros.h"
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef _WIN32
#include <unistd.h>
#endif
#include <assert.h>
#include <errno.h>
#include <ctype.h>
......@@ -40,6 +42,9 @@
#include "hiredis.h"
#include "net.h"
#include "sds.h"
#ifdef _WIN32
#include "../../src/win32_Interop/win32fixes.h"
#endif
static redisReply *createReplyObject(int type);
static void *createStringObject(const redisReadTask *task, char *str, size_t len);
......@@ -116,7 +121,7 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
memcpy(buf,str,len);
buf[len] = '\0';
r->str = buf;
r->len = len;
r->len = (int)len;
if (task->parent) {
parent = task->parent->obj;
......@@ -259,7 +264,7 @@ static char *readBytes(redisReader *r, unsigned int bytes) {
/* Find pointer to \r\n. */
static char *seekNewline(char *s, size_t len) {
int pos = 0;
int _len = len-1;
int _len = (int)(len-1);
/* Position should be < len-1 because the character at "pos" should be
* followed by a \n. Note that strchr cannot be used because it doesn't
......@@ -319,7 +324,7 @@ static char *readLine(redisReader *r, int *_len) {
p = r->buf+r->pos;
s = seekNewline(p,(r->len-r->pos));
if (s != NULL) {
len = s-(r->buf+r->pos);
len = (int)(s-(r->buf+r->pos));
r->pos += len+2; /* skip \r\n */
if (_len) *_len = len;
return p;
......@@ -390,7 +395,11 @@ static int processBulkItem(redisReader *r) {
redisReadTask *cur = &(r->rstack[r->ridx]);
void *obj = NULL;
char *p, *s;
#ifdef _WIN32
long long len;
#else
long len;
#endif
unsigned long bytelen;
int success = 0;
......@@ -398,7 +407,7 @@ static int processBulkItem(redisReader *r) {
s = seekNewline(p,r->len-r->pos);
if (s != NULL) {
p = r->buf+r->pos;
bytelen = s-(r->buf+r->pos)+2; /* include \r\n */
bytelen = (int)(s-(r->buf+r->pos)+2); /* include \r\n */
len = readLongLong(p);
if (len < 0) {
......@@ -410,10 +419,10 @@ static int processBulkItem(redisReader *r) {
success = 1;
} else {
/* Only continue when the buffer contains the entire bulk item. */
bytelen += len+2; /* include \r\n */
bytelen += (unsigned long)len+2; /* include \r\n */
if (r->pos+bytelen <= r->len) {
if (r->fn && r->fn->createString)
obj = r->fn->createString(cur,s+2,len);
obj = r->fn->createString(cur,s+2,(size_t)len);
else
obj = (void*)REDIS_REPLY_STRING;
success = 1;
......@@ -443,7 +452,11 @@ static int processMultiBulkItem(redisReader *r) {
redisReadTask *cur = &(r->rstack[r->ridx]);
void *obj;
char *p;
#ifdef _WIN32
long long elements;
#else
long elements;
#endif
int root = 0;
/* Set error for nested multi bulks with depth > 7 */
......@@ -471,7 +484,7 @@ static int processMultiBulkItem(redisReader *r) {
moveToNextTask(r);
} else {
if (r->fn && r->fn->createArray)
obj = r->fn->createArray(cur,elements);
obj = r->fn->createArray(cur,(int)elements);
else
obj = (void*)REDIS_REPLY_ARRAY;
......@@ -482,7 +495,7 @@ static int processMultiBulkItem(redisReader *r) {
/* Modify task stack when there are more than 0 elements. */
if (elements > 0) {
cur->elements = elements;
cur->elements = (int)elements;
cur->obj = obj;
r->ridx++;
r->rstack[r->ridx].type = -1;
......@@ -680,7 +693,7 @@ static int intlen(int i) {
/* Helper that calculates the bulk length given a certain string length. */
static size_t bulklen(size_t len) {
return 1+intlen(len)+2+len+2;
return (size_t)(1+intlen((int)len)+2+(int)len+2);
}
int redisvFormatCommand(char **target, const char *format, va_list ap) {
......@@ -711,7 +724,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
if (newargv == NULL) goto err;
curargv = newargv;
curargv[argc++] = curarg;
totlen += bulklen(sdslen(curarg));
totlen += (int)bulklen(sdslen(curarg));
/* curarg is put in argv so it can be overwritten. */
curarg = sdsempty();
......@@ -863,7 +876,7 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
if (newargv == NULL) goto err;
curargv = newargv;
curargv[argc++] = curarg;
totlen += bulklen(sdslen(curarg));
totlen += (int)bulklen(sdslen(curarg));
} else {
sdsfree(curarg);
}
......@@ -875,14 +888,18 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
totlen += 1+intlen(argc)+2;
/* Build the command at protocol level */
cmd = malloc(totlen+1);
cmd = (char *)malloc(totlen+1);
if (cmd == NULL) goto err;
pos = sprintf(cmd,"*%d\r\n",argc);
for (j = 0; j < argc; j++) {
#ifdef _WIN32
pos += sprintf(cmd+pos,"$%llu\r\n",(unsigned long long)sdslen(curargv[j]));
#else
pos += sprintf(cmd+pos,"$%zu\r\n",sdslen(curargv[j]));
#endif
memcpy(cmd+pos,curargv[j],sdslen(curargv[j]));
pos += sdslen(curargv[j]);
pos += (int)sdslen(curargv[j]);
sdsfree(curargv[j]);
cmd[pos++] = '\r';
cmd[pos++] = '\n';
......@@ -946,7 +963,7 @@ int redisFormatCommandArgv(char **target, int argc, const char **argv, const siz
totlen = 1+intlen(argc)+2;
for (j = 0; j < argc; j++) {
len = argvlen ? argvlen[j] : strlen(argv[j]);
totlen += bulklen(len);
totlen += (int)bulklen(len);
}
/* Build the command at protocol level */
......@@ -957,9 +974,13 @@ int redisFormatCommandArgv(char **target, int argc, const char **argv, const siz
pos = sprintf(cmd,"*%d\r\n",argc);
for (j = 0; j < argc; j++) {
len = argvlen ? argvlen[j] : strlen(argv[j]);
#ifdef _WIN32
pos += sprintf(cmd+pos,"$%llu\r\n",(unsigned long long)len);
#else
pos += sprintf(cmd+pos,"$%zu\r\n",len);
#endif
memcpy(cmd+pos,argv[j],len);
pos += len;
pos += (int)len;
cmd[pos++] = '\r';
cmd[pos++] = '\n';
}
......@@ -1001,8 +1022,9 @@ static redisContext *redisContextInit(void) {
}
void redisFree(redisContext *c) {
if (c->fd > 0)
if (c->fd > 0) {
close(c->fd);
}
if (c->obuf != NULL)
sdsfree(c->obuf);
if (c->reader != NULL)
......@@ -1055,6 +1077,31 @@ redisContext *redisConnectUnixNonBlock(const char *path) {
return c;
}
/* initializers if caller handles connection */
redisContext *redisConnected() {
redisContext *c = redisContextInit();
c->fd = -1;
c->flags |= REDIS_BLOCK;
return c;
}
redisContext *redisConnectedNonBlock() {
redisContext *c = redisContextInit();
c->fd = -1;
c->flags &= ~REDIS_BLOCK;
return c;
}
#ifdef _WIN32
redisContext *redisPreConnectNonBlock(const char *ip, int port, struct sockaddr_in *sa) {
redisContext *c = redisContextInit();
c->fd = -1;
c->flags &= ~REDIS_BLOCK;
redisContextPreConnectTcp(c, ip, port, NULL, sa);
return c;
}
#endif
/* Set read/write timeout on a blocking socket. */
int redisSetTimeout(redisContext *c, struct timeval tv) {
if (c->flags & REDIS_BLOCK)
......@@ -1095,6 +1142,33 @@ int redisBufferRead(redisContext *c) {
return REDIS_OK;
}
#ifdef _WIN32
/* Use this function if the caller has already read the data. It will
* feed bytes to the reply parser.
*
* After this function is called, you may use redisContextReadReply to
* see if there is a reply available. */
int redisBufferReadDone(redisContext *c, char *buf, int nread) {
if (nread == -1) {
if (errno == EAGAIN && !(c->flags & REDIS_BLOCK)) {
/* Try again later */
} else {
__redisSetError(c,REDIS_ERR_IO,NULL);
return REDIS_ERR;
}
} else if (nread == 0) {
__redisSetError(c,REDIS_ERR_EOF, sdsnew("Server closed the connection"));
return REDIS_ERR;
} else {
if (redisReaderFeed(c->reader,buf,nread) != REDIS_OK) {
__redisSetError(c,c->reader->err,c->reader->errstr);
return REDIS_ERR;
}
}
return REDIS_OK;
}
#endif
/* Write the output buffer to the socket.
*
* Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was
......@@ -1133,6 +1207,23 @@ int redisBufferWrite(redisContext *c, int *done) {
return REDIS_OK;
}
#ifdef _WIN32
/* Use this function if the caller has already written the data.
*/
int redisBufferWriteDone(redisContext *c, int nwritten, int *done) {
if (nwritten > 0) {
if (nwritten == (signed)sdslen(c->obuf)) {
sdsfree(c->obuf);
c->obuf = sdsempty();
} else {
sdsrange(c->obuf, nwritten, -1);
}
}
if (done != NULL) *done = (sdslen(c->obuf) == 0);
return REDIS_OK;
}
#endif
/* Internal helper function to try and get a reply from the reader,
* or set an error in the context otherwise. */
int redisGetReplyFromReader(redisContext *c, void **reply) {
......
......@@ -33,7 +33,17 @@
#define __HIREDIS_H
#include <stdio.h> /* for size_t */
#include <stdarg.h> /* for va_list */
#ifndef _WIN32
#include <sys/time.h> /* for struct timeval */
#endif
#ifdef _WIN32
#include "..\..\src\win32_Interop\Win32_FDAPI.h"
#include <windows.h>
#ifndef va_copy
#define va_copy(d,s) d = (s)
#endif
#endif
#define HIREDIS_MAJOR 0
#define HIREDIS_MINOR 10
......@@ -176,10 +186,17 @@ redisContext *redisConnectNonBlock(const char *ip, int port);
redisContext *redisConnectUnix(const char *path);
redisContext *redisConnectUnixWithTimeout(const char *path, struct timeval tv);
redisContext *redisConnectUnixNonBlock(const char *path);
redisContext *redisConnected();
redisContext *redisConnectedNonBlock();
int redisSetTimeout(redisContext *c, struct timeval tv);
void redisFree(redisContext *c);
int redisBufferRead(redisContext *c);
int redisBufferWrite(redisContext *c, int *done);
#ifdef _WIN32
redisContext *redisPreConnectNonBlock(const char *ip, int port, struct sockaddr_in *sa);
int redisBufferReadDone(redisContext *c, char *buf, int nread);
int redisBufferWriteDone(redisContext *c, int nwritten, int *done);
#endif
/* In a blocking context, this function first checks if there are unconsumed
* replies to return and returns one if so. Otherwise, it flushes the output
......
......@@ -32,6 +32,7 @@
#include "fmacros.h"
#include <sys/types.h>
#ifndef _WIN32
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/un.h>
......@@ -39,17 +40,23 @@
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#endif
#include <fcntl.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#ifndef _WIN32
#include <poll.h>
#endif
#include <limits.h>
#include "net.h"
#include "sds.h"
#ifdef _WIN32
#include "../../src/win32_Interop/win32fixes.h"
#endif
/* Defined in hiredis.c */
void __redisSetError(redisContext *c, int type, const char *str);
......@@ -94,7 +101,7 @@ static int redisSetBlocking(redisContext *c, int fd, int blocking) {
/* Set the socket nonblocking.
* Note that fcntl(2) for F_GETFL and F_SETFL can't be
* interrupted by a signal. */
if ((flags = fcntl(fd, F_GETFL)) == -1) {
if ((flags = fcntl(fd, F_GETFL,0)) == -1) {
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)");
close(fd);
return REDIS_ERR;
......@@ -192,6 +199,7 @@ int redisCheckSocketError(redisContext *c, int fd) {
return REDIS_OK;
}
int redisContextSetTimeout(redisContext *c, struct timeval tv) {
if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)");
......@@ -204,6 +212,107 @@ int redisContextSetTimeout(redisContext *c, struct timeval tv) {
return REDIS_OK;
}
#ifdef _WIN32
int redisContextPreConnectTcp(redisContext *c, const char *addr, int port,
struct timeval *timeout, struct sockaddr_in *sa) {
int s;
int blocking = (c->flags & REDIS_BLOCK);
unsigned long inAddress;
if ((s = redisCreateSocket(c,AF_INET)) < 0) {
return REDIS_ERR;
}
sa->sin_family = AF_INET;
sa->sin_port = htons(port);
inAddress = inet_addr(addr);
if (inAddress == INADDR_NONE || inAddress == INADDR_ANY) {
struct hostent *he;
he = gethostbyname(addr);
if (he == NULL) {
__redisSetError(c,REDIS_ERR_OTHER,
sdscatprintf(sdsempty(),"can't resolve: %s\n", addr));
close(s);
return REDIS_ERR;
}
memcpy(&sa->sin_addr, he->h_addr, sizeof(struct in_addr));
}
else {
sa->sin_addr.s_addr = inAddress;
}
if (redisSetTcpNoDelay(c,s) != REDIS_OK)
return REDIS_ERR;
if (blocking == 0) {
if (redisSetBlocking(c,s,0) != REDIS_OK)
return REDIS_ERR;
}
c->fd = s;
return REDIS_OK;
}
int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) {
int s;
int blocking = (c->flags & REDIS_BLOCK);
struct sockaddr_in sa;
unsigned long inAddress;
if ((s = redisCreateSocket(c,AF_INET)) < 0)
return REDIS_ERR;
sa.sin_family = AF_INET;
sa.sin_port = htons(port);
inAddress = inet_addr(addr);
if (inAddress == INADDR_NONE || inAddress == INADDR_ANY) {
struct hostent *he;
he = gethostbyname(addr);
if (he == NULL) {
__redisSetError(c,REDIS_ERR_OTHER,
sdscatprintf(sdsempty(),"can't resolve: %s\n", addr));
close(s);
return REDIS_ERR;
}
memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
}
else {
sa.sin_addr.s_addr = inAddress;
}
if (redisSetTcpNoDelay(c,s) != REDIS_OK)
return REDIS_ERR;
if (blocking == 0) {
if (redisSetBlocking(c,s,0) != REDIS_OK)
return REDIS_ERR;
}
if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
errno = WSAGetLastError();
if ((errno == WSAEINVAL) || (errno == WSAEWOULDBLOCK))
errno = EINPROGRESS;
if (errno == EINPROGRESS && !blocking) {
/* This is ok. */
} else {
if (redisContextWaitReady(c,s,timeout) != REDIS_OK)
return REDIS_ERR;
}
}
if (blocking) {
if (redisSetBlocking(c,s,1) != REDIS_OK)
return REDIS_ERR;
}
c->fd = s;
c->flags |= REDIS_CONNECTED;
return REDIS_OK;
}
#else
int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout) {
int s, rv;
char _port[6]; /* strlen("65535"); */
......@@ -267,7 +376,17 @@ end:
freeaddrinfo(servinfo);
return rv; // Need to return REDIS_OK if alright
}
#endif
#ifdef _WIN32
int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout) {
(void) timeout;
__redisSetError(c,REDIS_ERR_IO,
sdscatprintf(sdsempty(),"Unix sockets are not suported on Windows platform. (%s)\n", path));
return REDIS_ERR;
}
#else
int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout) {
int s;
int blocking = (c->flags & REDIS_BLOCK);
......@@ -297,3 +416,4 @@ int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *t
c->flags |= REDIS_CONNECTED;
return REDIS_OK;
}
#endif
......@@ -43,5 +43,8 @@ int redisCheckSocketError(redisContext *c, int fd);
int redisContextSetTimeout(redisContext *c, struct timeval tv);
int redisContextConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout);
int redisContextConnectUnix(redisContext *c, const char *path, struct timeval *timeout);
#ifdef _WIN32
int redisContextPreConnectTcp(redisContext *c, const char *addr, int port, struct timeval *timeout, struct sockaddr_in *sa);
#endif
#endif
......@@ -57,7 +57,7 @@ sds sdsnewlen(const void *init, size_t initlen) {
sh = zcalloc(sizeof(struct sdshdr)+initlen+1);
}
if (sh == NULL) return NULL;
sh->len = initlen;
sh->len = (int)initlen;
sh->free = 0;
if (initlen && init)
memcpy(sh->buf, init, initlen);
......@@ -104,7 +104,7 @@ void sdsfree(sds s) {
* remains 6 bytes. */
void sdsupdatelen(sds s) {
struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
int reallen = strlen(s);
int reallen = (int)strlen(s);
sh->free += (sh->len-reallen);
sh->len = reallen;
}
......@@ -142,7 +142,7 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {
newsh = zrealloc(sh, sizeof(struct sdshdr)+newlen+1);
if (newsh == NULL) return NULL;
newsh->free = newlen - len;
newsh->free = (int)(newlen - len);
return newsh->buf;
}
......@@ -224,8 +224,8 @@ sds sdsgrowzero(sds s, size_t len) {
sh = (void*)(s-(sizeof(struct sdshdr)));
memset(s+curlen,0,(len-curlen+1)); /* also set trailing \0 byte */
totlen = sh->len+sh->free;
sh->len = len;
sh->free = totlen-sh->len;
sh->len = (int)len;
sh->free = (int)(totlen-sh->len);
return s;
}
......@@ -242,8 +242,8 @@ sds sdscatlen(sds s, const void *t, size_t len) {
if (s == NULL) return NULL;
sh = (void*) (s-(sizeof(struct sdshdr)));
memcpy(s+curlen, t, len);
sh->len = curlen+len;
sh->free = sh->free-len;
sh->len = (int)(curlen+len);
sh->free = (int)(sh->free-len);
s[curlen+len] = '\0';
return s;
}
......@@ -278,8 +278,8 @@ sds sdscpylen(sds s, const char *t, size_t len) {
}
memcpy(s, t, len);
s[len] = '\0';
sh->len = len;
sh->free = totlen-len;
sh->len = (int)len;
sh->free = (int)(totlen-len);
return s;
}
......@@ -364,8 +364,8 @@ sds sdstrim(sds s, const char *cset) {
len = (sp > ep) ? 0 : ((ep-sp)+1);
if (sh->buf != sp) memmove(sh->buf, sp, len);
sh->buf[len] = '\0';
sh->free = sh->free+(sh->len-len);
sh->len = len;
sh->free = (int)(sh->free+(sh->len-len));
sh->len = (int)len;
return s;
}
......@@ -391,11 +391,11 @@ void sdsrange(sds s, int start, int end) {
if (len == 0) return;
if (start < 0) {
start = len+start;
start = (int)(len+start);
if (start < 0) start = 0;
}
if (end < 0) {
end = len+end;
end = (int)(len+end);
if (end < 0) end = 0;
}
newlen = (start > end) ? 0 : (end-start)+1;
......@@ -403,7 +403,7 @@ void sdsrange(sds s, int start, int end) {
if (start >= (signed)len) {
newlen = 0;
} else if (end >= (signed)len) {
end = len-1;
end = (int)(len-1);
newlen = (start > end) ? 0 : (end-start)+1;
}
} else {
......@@ -411,20 +411,20 @@ void sdsrange(sds s, int start, int end) {
}
if (start && newlen) memmove(sh->buf, sh->buf+start, newlen);
sh->buf[newlen] = 0;
sh->free = sh->free+(sh->len-newlen);
sh->len = newlen;
sh->free = (int)(sh->free+(sh->len-newlen));
sh->len = (int)newlen;
}
/* Apply tolower() to every character of the sds string 's'. */
void sdstolower(sds s) {
int len = sdslen(s), j;
int len = (int)sdslen(s), j;
for (j = 0; j < len; j++) s[j] = tolower(s[j]);
}
/* Apply toupper() to every character of the sds string 's'. */
void sdstoupper(sds s) {
int len = sdslen(s), j;
int len = (int)sdslen(s), j;
for (j = 0; j < len; j++) s[j] = toupper(s[j]);
}
......@@ -448,7 +448,7 @@ int sdscmp(const sds s1, const sds s2) {
l2 = sdslen(s2);
minlen = (l1 < l2) ? l1 : l2;
cmp = memcmp(s1,s2,minlen);
if (cmp == 0) return l1-l2;
if (cmp == 0) return (int)(l1-l2);
return cmp;
}
......
......@@ -36,21 +36,26 @@
#include <sys/types.h>
#include <stdarg.h>
#ifdef _WIN32
#define inline __inline
#define va_copy(d,s) d = (s)
#endif
typedef char *sds;
struct sdshdr {
int len;
int free;
char buf[];
char* buf;
};
static inline size_t sdslen(const sds s) {
struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
struct sdshdr *sh = (struct sdshdr *)(s-(sizeof(struct sdshdr)));
return sh->len;
}
static inline size_t sdsavail(const sds s) {
struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr)));
struct sdshdr *sh = (struct sdshdr *)(s-(sizeof(struct sdshdr)));
return sh->free;
}
......
Unless otherwise specified, files in the jemalloc source distribution are
subject to the following license:
--------------------------------------------------------------------------------
Copyright (C) 2002-2012 Jason Evans <jasone@canonware.com>.
All rights reserved.
Copyright (C) 2007-2012 Mozilla Foundation. All rights reserved.
Copyright (C) 2009-2012 Facebook, 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:
1. Redistributions of source code must retain the above copyright notice(s),
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice(s),
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 HOLDER(S) ``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(S) 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.
--------------------------------------------------------------------------------
Building and installing jemalloc can be as simple as typing the following while
in the root directory of the source tree:
./configure
make
make install
=== Advanced configuration =====================================================
The 'configure' script supports numerous options that allow control of which
functionality is enabled, where jemalloc is installed, etc. Optionally, pass
any of the following arguments (not a definitive list) to 'configure':
--help
Print a definitive list of options.
--prefix=<install-root-dir>
Set the base directory in which to install. For example:
./configure --prefix=/usr/local
will cause files to be installed into /usr/local/include, /usr/local/lib,
and /usr/local/man.
--with-rpath=<colon-separated-rpath>
Embed one or more library paths, so that libjemalloc can find the libraries
it is linked to. This works only on ELF-based systems.
--with-mangling=<map>
Mangle public symbols specified in <map> which is a comma-separated list of
name:mangled pairs.
For example, to use ld's --wrap option as an alternative method for
overriding libc's malloc implementation, specify something like:
--with-mangling=malloc:__wrap_malloc,free:__wrap_free[...]
Note that mangling happens prior to application of the prefix specified by
--with-jemalloc-prefix, and mangled symbols are then ignored when applying
the prefix.
--with-jemalloc-prefix=<prefix>
Prefix all public APIs with <prefix>. For example, if <prefix> is
"prefix_", API changes like the following occur:
malloc() --> prefix_malloc()
malloc_conf --> prefix_malloc_conf
/etc/malloc.conf --> /etc/prefix_malloc.conf
MALLOC_CONF --> PREFIX_MALLOC_CONF
This makes it possible to use jemalloc at the same time as the system
allocator, or even to use multiple copies of jemalloc simultaneously.
By default, the prefix is "", except on OS X, where it is "je_". On OS X,
jemalloc overlays the default malloc zone, but makes no attempt to actually
replace the "malloc", "calloc", etc. symbols.
--with-private-namespace=<prefix>
Prefix all library-private APIs with <prefix>. For shared libraries,
symbol visibility mechanisms prevent these symbols from being exported, but
for static libraries, naming collisions are a real possibility. By
default, the prefix is "" (empty string).
--with-install-suffix=<suffix>
Append <suffix> to the base name of all installed files, such that multiple
versions of jemalloc can coexist in the same installation directory. For
example, libjemalloc.so.0 becomes libjemalloc<suffix>.so.0.
--enable-cc-silence
Enable code that silences non-useful compiler warnings. This is helpful
when trying to tell serious warnings from those due to compiler
limitations, but it potentially incurs a performance penalty.
--enable-debug
Enable assertions and validation code. This incurs a substantial
performance hit, but is very useful during application development.
--disable-stats
Disable statistics gathering functionality. See the "opt.stats_print"
option documentation for usage details.
--enable-prof
Enable heap profiling and leak detection functionality. See the "opt.prof"
option documentation for usage details. When enabled, there are several
approaches to backtracing, and the configure script chooses the first one
in the following list that appears to function correctly:
+ libunwind (requires --enable-prof-libunwind)
+ libgcc (unless --disable-prof-libgcc)
+ gcc intrinsics (unless --disable-prof-gcc)
--enable-prof-libunwind
Use the libunwind library (http://www.nongnu.org/libunwind/) for stack
backtracing.
--disable-prof-libgcc
Disable the use of libgcc's backtracing functionality.
--disable-prof-gcc
Disable the use of gcc intrinsics for backtracing.
--with-static-libunwind=<libunwind.a>
Statically link against the specified libunwind.a rather than dynamically
linking with -lunwind.
--disable-tcache
Disable thread-specific caches for small objects. Objects are cached and
released in bulk, thus reducing the total number of mutex operations. See
the "opt.tcache" option for usage details.
--enable-mremap
Enable huge realloc() via mremap(2). mremap() is disabled by default
because the flavor used is specific to Linux, which has a quirk in its
virtual memory allocation algorithm that causes semi-permanent VM map holes
under normal jemalloc operation.
--disable-munmap
Disable virtual memory deallocation via munmap(2); instead keep track of
the virtual memory for later use. munmap() is disabled by default (i.e.
--disable-munmap is implied) on Linux, which has a quirk in its virtual
memory allocation algorithm that causes semi-permanent VM map holes under
normal jemalloc operation.
--enable-dss
Enable support for page allocation/deallocation via sbrk(2), in addition to
mmap(2).
--disable-fill
Disable support for junk/zero filling of memory, quarantine, and redzones.
See the "opt.junk", "opt.zero", "opt.quarantine", and "opt.redzone" option
documentation for usage details.
--disable-valgrind
Disable support for Valgrind.
--disable-experimental
Disable support for the experimental API (*allocm()).
--enable-utrace
Enable utrace(2)-based allocation tracing. This feature is not broadly
portable (FreeBSD has it, but Linux and OS X do not).
--enable-xmalloc
Enable support for optional immediate termination due to out-of-memory
errors, as is commonly implemented by "xmalloc" wrapper function for malloc.
See the "opt.xmalloc" option documentation for usage details.
--enable-lazy-lock
Enable code that wraps pthread_create() to detect when an application
switches from single-threaded to multi-threaded mode, so that it can avoid
mutex locking/unlocking operations while in single-threaded mode. In
practice, this feature usually has little impact on performance unless
thread-specific caching is disabled.
--disable-tls
Disable thread-local storage (TLS), which allows for fast access to
thread-local variables via the __thread keyword. If TLS is available,
jemalloc uses it for several purposes.
--with-xslroot=<path>
Specify where to find DocBook XSL stylesheets when building the
documentation.
The following environment variables (not a definitive list) impact configure's
behavior:
CFLAGS="?"
Pass these flags to the compiler. You probably shouldn't define this unless
you know what you are doing. (Use EXTRA_CFLAGS instead.)
EXTRA_CFLAGS="?"
Append these flags to CFLAGS. This makes it possible to add flags such as
-Werror, while allowing the configure script to determine what other flags
are appropriate for the specified configuration.
The configure script specifically checks whether an optimization flag (-O*)
is specified in EXTRA_CFLAGS, and refrains from specifying an optimization
level if it finds that one has already been specified.
CPPFLAGS="?"
Pass these flags to the C preprocessor. Note that CFLAGS is not passed to
'cpp' when 'configure' is looking for include files, so you must use
CPPFLAGS instead if you need to help 'configure' find header files.
LD_LIBRARY_PATH="?"
'ld' uses this colon-separated list to find libraries.
LDFLAGS="?"
Pass these flags when linking.
PATH="?"
'configure' uses this to find programs.
=== Advanced compilation =======================================================
To build only parts of jemalloc, use the following targets:
build_lib_shared
build_lib_static
build_lib
build_doc_html
build_doc_man
build_doc
To install only parts of jemalloc, use the following targets:
install_bin
install_include
install_lib_shared
install_lib_static
install_lib
install_doc_html
install_doc_man
install_doc
To clean up build results to varying degrees, use the following make targets:
clean
distclean
relclean
=== Advanced installation ======================================================
Optionally, define make variables when invoking make, including (not
exclusively):
INCLUDEDIR="?"
Use this as the installation prefix for header files.
LIBDIR="?"
Use this as the installation prefix for libraries.
MANDIR="?"
Use this as the installation prefix for man pages.
DESTDIR="?"
Prepend DESTDIR to INCLUDEDIR, LIBDIR, DATADIR, and MANDIR. This is useful
when installing to a different path than was specified via --prefix.
CC="?"
Use this to invoke the C compiler.
CFLAGS="?"
Pass these flags to the compiler.
CPPFLAGS="?"
Pass these flags to the C preprocessor.
LDFLAGS="?"
Pass these flags when linking.
PATH="?"
Use this to search for programs used during configuration and building.
=== Development ================================================================
If you intend to make non-trivial changes to jemalloc, use the 'autogen.sh'
script rather than 'configure'. This re-generates 'configure', enables
configuration dependency rules, and enables re-generation of automatically
generated source files.
The build system supports using an object directory separate from the source
tree. For example, you can create an 'obj' directory, and from within that
directory, issue configuration and build commands:
autoconf
mkdir obj
cd obj
../configure --enable-autogen
make
=== Documentation ==============================================================
The manual page is generated in both html and roff formats. Any web browser
can be used to view the html manual. The roff manual page can be formatted
prior to installation via the following command:
nroff -man -t doc/jemalloc.3
jemalloc is a general-purpose scalable concurrent malloc(3) implementation.
This distribution is a "portable" implementation that currently targets
FreeBSD, Linux, Apple OS X, and MinGW. jemalloc is included as the default
allocator in the FreeBSD and NetBSD operating systems, and it is used by the
Mozilla Firefox web browser on Microsoft Windows-related platforms. Depending
on your needs, one of the other divergent versions may suit your needs better
than this distribution.
The COPYING file contains copyright and licensing information.
The INSTALL file contains information on how to configure, build, and install
jemalloc.
The ChangeLog file contains a brief summary of changes for each release.
URL: http://www.canonware.com/jemalloc/
#!/bin/sh
for i in autoconf; do
echo "$i"
$i
if [ $? -ne 0 ]; then
echo "Error $? in $i"
exit 1
fi
done
echo "./configure --enable-autogen $@"
./configure --enable-autogen $@
if [ $? -ne 0 ]; then
echo "Error $? in ./configure"
exit 1
fi
#!/bin/sh
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
@LD_PRELOAD_VAR@=${libdir}/libjemalloc.@SOREV@
export @LD_PRELOAD_VAR@
exec "$@"
此差异已折叠。
此差异已折叠。
此差异已折叠。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:import href="@XSLROOT@/html/docbook.xsl"/>
<xsl:import href="@abs_srcroot@doc/stylesheet.xsl"/>
</xsl:stylesheet>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:import href="@XSLROOT@/manpages/docbook.xsl"/>
<xsl:import href="@abs_srcroot@doc/stylesheet.xsl"/>
</xsl:stylesheet>
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册