Hello community, here is the log from the commit of package hiredis for openSUSE:Factory checked in at 2015-11-26 17:01:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/hiredis (Old) and /work/SRC/openSUSE:Factory/.hiredis.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "hiredis" Changes: -------- --- /work/SRC/openSUSE:Factory/hiredis/hiredis.changes 2015-03-05 18:16:31.000000000 +0100 +++ /work/SRC/openSUSE:Factory/.hiredis.new/hiredis.changes 2015-11-26 17:02:19.000000000 +0100 @@ -1,0 +2,25 @@ +Sun Nov 22 08:50:22 UTC 2015 - [email protected] + +- Update to 0.13.3 + * Revert "Clear `REDIS_CONNECTED` flag when connection is + closed". + * Make tests pass on FreeBSD +- Changes for 0.13.2 + * Prevent crash on pending replies in async code + * Clear `REDIS_CONNECTED` flag when connection is closed + * Add MacOS X addapter + * Add Qt adapter + * Add Ivykis adapter +- Changes for 0.13.1 + * Fix memory leak in async reply handling + * Rename struct member to avoid name clash with pre-c99 code +- Changes for 0.13.0 + * Windows compatibility layer for parser code + * Properly escape data printed to PKGCONF file + * Fix tests when assert() undefined + * Implement a reconnect method for the client context, this + changes the structure of `redisContext` +- Drop hiredis-pkgconfig.patch + * fixed in upstream + +------------------------------------------------------------------- Old: ---- hiredis-pkgconfig.patch v0.12.1.tar.gz New: ---- v0.13.3.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ hiredis.spec ++++++ --- /var/tmp/diff_new_pack.8qC16B/_old 2015-11-26 17:02:19.000000000 +0100 +++ /var/tmp/diff_new_pack.8qC16B/_new 2015-11-26 17:02:19.000000000 +0100 @@ -16,16 +16,15 @@ # -%global libname lib%{name}0_12 +%global libname lib%{name}0_13 Name: hiredis -Version: 0.12.1 +Version: 0.13.3 Release: 0 Summary: Minimalistic C client for Redis License: BSD-3-Clause Group: Productivity/Databases/Clients Url: https://github.com/redis/hiredis Source0: https://github.com/redis/hiredis/archive/v%{version}.tar.gz -Patch0: hiredis-pkgconfig.patch BuildRequires: pkg-config BuildRoot: %{_tmppath}/%{name}-%{version}-build @@ -52,7 +51,6 @@ %prep %setup -q -%patch0 -p1 %build make %{?_smp_mflags} OPTIMIZATION="%{optflags}" PREFIX=%{_prefix} LIBRARY_PATH=%{_lib} ++++++ v0.12.1.tar.gz -> v0.13.3.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/.travis.yml new/hiredis-0.13.3/.travis.yml --- old/hiredis-0.12.1/.travis.yml 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/.travis.yml 2015-09-16 12:25:02.000000000 +0200 @@ -1,15 +1,24 @@ language: c +sudo: false compiler: - gcc - clang +addons: + apt: + packages: + - libc6-dbg + - libc6-dev + - libc6:i386 + - libc6-dev-i386 + - libc6-dbg:i386 + - gcc-multilib + - valgrind + env: - CFLAGS="-Werror" - PRE="valgrind --track-origins=yes --leak-check=full" - - TARGET="32bit" CFLAGS="-Werror" - - TARGET="32bit" PRE="valgrind --track-origins=yes --leak-check=full" - -install: - - sudo apt-get install libc6-dbg libc6-dev libc6-i686:i386 libc6-dev-i386 libc6-dbg:i386 valgrind -y + - TARGET="32bit" TARGET_VARS="32bit-vars" CFLAGS="-Werror" + - TARGET="32bit" TARGET_VARS="32bit-vars" PRE="valgrind --track-origins=yes --leak-check=full" -script: make $TARGET CFLAGS="$CFLAGS" && make check PRE="$PRE" +script: make $TARGET CFLAGS="$CFLAGS" && make check PRE="$PRE" && make $TARGET_VARS hiredis-example diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/CHANGELOG.md new/hiredis-0.13.3/CHANGELOG.md --- old/hiredis-0.12.1/CHANGELOG.md 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/CHANGELOG.md 2015-09-16 12:25:02.000000000 +0200 @@ -1,9 +1,51 @@ -### 0.12.1 - January 26, 2015 +### 0.13.3 (2015-09-16) + +* Revert "Clear `REDIS_CONNECTED` flag when connection is closed". +* Make tests pass on FreeBSD (Thanks, Giacomo Olgeni) + + +If the `REDIS_CONNECTED` flag is cleared, +the async onDisconnect callback function will never be called. +This causes problems as the disconnect is never reported back to the user. + +### 0.13.2 (2015-08-25) + +* Prevent crash on pending replies in async code (Thanks, @switch-st) +* Clear `REDIS_CONNECTED` flag when connection is closed (Thanks, Jerry Jacobs) +* Add MacOS X addapter (Thanks, @dizzus) +* Add Qt adapter (Thanks, Pietro Cerutti) +* Add Ivykis adapter (Thanks, Gergely Nagy) + +All adapters are provided as is and are only tested where possible. + +### 0.13.1 (2015-05-03) + +This is a bug fix release. +The new `reconnect` method introduced new struct members, which clashed with pre-defined names in pre-C99 code. +Another commit forced C99 compilation just to make it work, but of course this is not desirable for outside projects. +Other non-C99 code can now use hiredis as usual again. +Sorry for the inconvenience. + +* Fix memory leak in async reply handling (Salvatore Sanfilippo) +* Rename struct member to avoid name clash with pre-c99 code (Alex Balashov, ncopa) + +### 0.13.0 (2015-04-16) + +This release adds a minimal Windows compatibility layer. +The parser, standalone since v0.12.0, can now be compiled on Windows +(and thus used in other client libraries as well) + +* Windows compatibility layer for parser code (tzickel) +* Properly escape data printed to PKGCONF file (Dan Skorupski) +* Fix tests when assert() undefined (Keith Bennett, Matt Stancliff) +* Implement a reconnect method for the client context, this changes the structure of `redisContext` (Aaron Bedra) + +### 0.12.1 (2015-01-26) * Fix `make install`: DESTDIR support, install all required files, install PKGCONF in proper location * Fix `make test` as 32 bit build on 64 bit platform -### 0.12.0 - January 22, 2015 +### 0.12.0 (2015-01-22) * Add optional KeepAlive support diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/Makefile new/hiredis-0.13.3/Makefile --- old/hiredis-0.12.1/Makefile 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/Makefile 2015-09-16 12:25:02.000000000 +0200 @@ -12,6 +12,7 @@ HIREDIS_MAJOR=$(shell grep HIREDIS_MAJOR hiredis.h | awk '{print $$3}') HIREDIS_MINOR=$(shell grep HIREDIS_MINOR hiredis.h | awk '{print $$3}') HIREDIS_PATCH=$(shell grep HIREDIS_PATCH hiredis.h | awk '{print $$3}') +HIREDIS_SONAME=$(shell grep HIREDIS_SONAME hiredis.h | awk '{print $$3}') # Installation related variables and target PREFIX?=/usr/local @@ -36,6 +37,7 @@ # Fallback to gcc when $CC is not in $PATH. CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc') +CXX:=$(shell sh -c 'type $(CXX) >/dev/null 2>/dev/null && echo $(CXX) || echo g++') OPTIMIZATION?=-O3 WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings DEBUG?= -g -ggdb @@ -44,7 +46,7 @@ DYLIBSUFFIX=so STLIBSUFFIX=a -DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR).$(HIREDIS_MINOR) +DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_SONAME) DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR) DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX) DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS) @@ -60,8 +62,7 @@ endif ifeq ($(uname_S),Darwin) DYLIBSUFFIX=dylib - DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(DYLIBSUFFIX) - DYLIB_MAJOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(DYLIBSUFFIX) + DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_SONAME).$(DYLIBSUFFIX) DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS) endif @@ -95,6 +96,12 @@ hiredis-example-glib: examples/example-glib.c adapters/glib.h $(STLIBNAME) $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) $(shell pkg-config --cflags --libs glib-2.0) -I. $< $(STLIBNAME) +hiredis-example-ivykis: examples/example-ivykis.c adapters/ivykis.h $(STLIBNAME) + $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -livykis $(STLIBNAME) + +hiredis-example-macosx: examples/example-macosx.c adapters/macosx.h $(STLIBNAME) + $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -framework CoreFoundation $(STLIBNAME) + ifndef AE_DIR hiredis-example-ae: @echo "Please specify AE_DIR (e.g. <redis repository>/src)" @@ -110,7 +117,20 @@ @false else hiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME) - $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread $(STLIBNAME) + $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread -lrt $(STLIBNAME) +endif + +ifeq ($(and $(QT_MOC),$(QT_INCLUDE_DIR),$(QT_LIBRARY_DIR)),) +hiredis-example-qt: + @echo "Please specify QT_MOC, QT_INCLUDE_DIR AND QT_LIBRARY_DIR" + @false +else +hiredis-example-qt: examples/example-qt.cpp adapters/qt.h $(STLIBNAME) + $(QT_MOC) adapters/qt.h -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore | \ + $(CXX) -x c++ -o qt-adapter-moc.o -c - $(REAL_CFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore + $(QT_MOC) examples/example-qt.h -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore | \ + $(CXX) -x c++ -o qt-example-moc.o -c - $(REAL_CFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore + $(CXX) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore -L$(QT_LIBRARY_DIR) qt-adapter-moc.o qt-example-moc.o $< -pthread $(STLIBNAME) -lQtCore endif hiredis-example: examples/example.c $(STLIBNAME) @@ -150,22 +170,21 @@ $(PKGCONFNAME): hiredis.h @echo "Generating $@ for pkgconfig..." @echo prefix=$(PREFIX) > $@ - @echo exec_prefix=$${prefix} >> $@ - @echo libdir=$(INSTALL_LIBRARY_PATH) >> $@ - @echo includedir=$(INSTALL_INCLUDE_PATH) >> $@ + @echo exec_prefix=\$${prefix} >> $@ + @echo libdir=$(PREFIX)/$(LIBRARY_PATH) >> $@ + @echo includedir=$(PREFIX)/$(INCLUDE_PATH) >> $@ @echo >> $@ @echo Name: hiredis >> $@ @echo Description: Minimalistic C client library for Redis. >> $@ @echo Version: $(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(HIREDIS_PATCH) >> $@ - @echo Libs: -L$${libdir} -lhiredis >> $@ - @echo Cflags: -I$${includedir} -D_FILE_OFFSET_BITS=64 >> $@ + @echo Libs: -L\$${libdir} -lhiredis >> $@ + @echo Cflags: -I\$${includedir} -D_FILE_OFFSET_BITS=64 >> $@ -install: $(DYLIBNAME) $(STLIBNAME) +install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME) mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH) $(INSTALL) hiredis.h async.h read.h sds.h adapters $(INSTALL_INCLUDE_PATH) $(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME) - cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME) - cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MAJOR_NAME) $(DYLIBNAME) + cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIBNAME) $(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH) mkdir -p $(INSTALL_PKGCONF_PATH) $(INSTALL) $(PKGCONFNAME) $(INSTALL_PKGCONF_PATH) @@ -176,6 +195,10 @@ @echo "" $(MAKE) CFLAGS="-m32" LDFLAGS="-m32" +32bit-vars: + $(eval CFLAGS=-m32) + $(eval LDFLAGS=-m32) + gprof: $(MAKE) CFLAGS="-pg" LDFLAGS="-pg" @@ -191,4 +214,4 @@ noopt: $(MAKE) OPTIMIZATION="" -.PHONY: all test check clean dep install 32bit gprof gcov noopt +.PHONY: all test check clean dep install 32bit 32bit-vars gprof gcov noopt diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/README.md new/hiredis-0.13.3/README.md --- old/hiredis-0.12.1/README.md 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/README.md 2015-09-16 12:25:02.000000000 +0200 @@ -387,4 +387,6 @@ ## AUTHORS Hiredis was written by Salvatore Sanfilippo (antirez at gmail) and -Pieter Noordhuis (pcnoordhuis at gmail) and is released under the BSD license. +Pieter Noordhuis (pcnoordhuis at gmail) and is released under the BSD license. +Hiredis is currently maintained by Matt Stancliff (matt at genges dot com) and +Jan-Erik Rediger (janerik at fnordig dot com) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/adapters/glib.h new/hiredis-0.13.3/adapters/glib.h --- old/hiredis-0.12.1/adapters/glib.h 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/adapters/glib.h 2015-09-16 12:25:02.000000000 +0200 @@ -16,43 +16,43 @@ static void redis_source_add_read (gpointer data) { - RedisSource *source = data; + RedisSource *source = (RedisSource *)data; g_return_if_fail(source); source->poll_fd.events |= G_IO_IN; - g_main_context_wakeup(g_source_get_context(data)); + g_main_context_wakeup(g_source_get_context((GSource *)data)); } static void redis_source_del_read (gpointer data) { - RedisSource *source = data; + RedisSource *source = (RedisSource *)data; g_return_if_fail(source); source->poll_fd.events &= ~G_IO_IN; - g_main_context_wakeup(g_source_get_context(data)); + g_main_context_wakeup(g_source_get_context((GSource *)data)); } static void redis_source_add_write (gpointer data) { - RedisSource *source = data; + RedisSource *source = (RedisSource *)data; g_return_if_fail(source); source->poll_fd.events |= G_IO_OUT; - g_main_context_wakeup(g_source_get_context(data)); + g_main_context_wakeup(g_source_get_context((GSource *)data)); } static void redis_source_del_write (gpointer data) { - RedisSource *source = data; + RedisSource *source = (RedisSource *)data; g_return_if_fail(source); source->poll_fd.events &= ~G_IO_OUT; - g_main_context_wakeup(g_source_get_context(data)); + g_main_context_wakeup(g_source_get_context((GSource *)data)); } static void redis_source_cleanup (gpointer data) { - RedisSource *source = data; + RedisSource *source = (RedisSource *)data; g_return_if_fail(source); @@ -63,7 +63,7 @@ * current main loop. However, we will remove the GPollFD. */ if (source->poll_fd.fd >= 0) { - g_source_remove_poll(data, &source->poll_fd); + g_source_remove_poll((GSource *)data, &source->poll_fd); source->poll_fd.fd = -1; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/adapters/ivykis.h new/hiredis-0.13.3/adapters/ivykis.h --- old/hiredis-0.12.1/adapters/ivykis.h 1970-01-01 01:00:00.000000000 +0100 +++ new/hiredis-0.13.3/adapters/ivykis.h 2015-09-16 12:25:02.000000000 +0200 @@ -0,0 +1,81 @@ +#ifndef __HIREDIS_IVYKIS_H__ +#define __HIREDIS_IVYKIS_H__ +#include <iv.h> +#include "../hiredis.h" +#include "../async.h" + +typedef struct redisIvykisEvents { + redisAsyncContext *context; + struct iv_fd fd; +} redisIvykisEvents; + +static void redisIvykisReadEvent(void *arg) { + redisAsyncContext *context = (redisAsyncContext *)arg; + redisAsyncHandleRead(context); +} + +static void redisIvykisWriteEvent(void *arg) { + redisAsyncContext *context = (redisAsyncContext *)arg; + redisAsyncHandleWrite(context); +} + +static void redisIvykisAddRead(void *privdata) { + redisIvykisEvents *e = (redisIvykisEvents*)privdata; + iv_fd_set_handler_in(&e->fd, redisIvykisReadEvent); +} + +static void redisIvykisDelRead(void *privdata) { + redisIvykisEvents *e = (redisIvykisEvents*)privdata; + iv_fd_set_handler_in(&e->fd, NULL); +} + +static void redisIvykisAddWrite(void *privdata) { + redisIvykisEvents *e = (redisIvykisEvents*)privdata; + iv_fd_set_handler_out(&e->fd, redisIvykisWriteEvent); +} + +static void redisIvykisDelWrite(void *privdata) { + redisIvykisEvents *e = (redisIvykisEvents*)privdata; + iv_fd_set_handler_out(&e->fd, NULL); +} + +static void redisIvykisCleanup(void *privdata) { + redisIvykisEvents *e = (redisIvykisEvents*)privdata; + + iv_fd_unregister(&e->fd); + free(e); +} + +static int redisIvykisAttach(redisAsyncContext *ac) { + redisContext *c = &(ac->c); + redisIvykisEvents *e; + + /* Nothing should be attached when something is already attached */ + if (ac->ev.data != NULL) + return REDIS_ERR; + + /* Create container for context and r/w events */ + e = (redisIvykisEvents*)malloc(sizeof(*e)); + e->context = ac; + + /* Register functions to start/stop listening for events */ + ac->ev.addRead = redisIvykisAddRead; + ac->ev.delRead = redisIvykisDelRead; + ac->ev.addWrite = redisIvykisAddWrite; + ac->ev.delWrite = redisIvykisDelWrite; + ac->ev.cleanup = redisIvykisCleanup; + ac->ev.data = e; + + /* Initialize and install read/write events */ + IV_FD_INIT(&e->fd); + e->fd.fd = c->fd; + e->fd.handler_in = redisIvykisReadEvent; + e->fd.handler_out = redisIvykisWriteEvent; + e->fd.handler_err = NULL; + e->fd.cookie = e->context; + + iv_fd_register(&e->fd); + + return REDIS_OK; +} +#endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/adapters/macosx.h new/hiredis-0.13.3/adapters/macosx.h --- old/hiredis-0.12.1/adapters/macosx.h 1970-01-01 01:00:00.000000000 +0100 +++ new/hiredis-0.13.3/adapters/macosx.h 2015-09-16 12:25:02.000000000 +0200 @@ -0,0 +1,114 @@ +// +// Created by Дмитрий Бахвалов on 13.07.15. +// Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved. +// + +#ifndef __HIREDIS_MACOSX_H__ +#define __HIREDIS_MACOSX_H__ + +#include <CoreFoundation/CoreFoundation.h> + +#include "../hiredis.h" +#include "../async.h" + +typedef struct { + redisAsyncContext *context; + CFSocketRef socketRef; + CFRunLoopSourceRef sourceRef; +} RedisRunLoop; + +static int freeRedisRunLoop(RedisRunLoop* redisRunLoop) { + if( redisRunLoop != NULL ) { + if( redisRunLoop->sourceRef != NULL ) { + CFRunLoopSourceInvalidate(redisRunLoop->sourceRef); + CFRelease(redisRunLoop->sourceRef); + } + if( redisRunLoop->socketRef != NULL ) { + CFSocketInvalidate(redisRunLoop->socketRef); + CFRelease(redisRunLoop->socketRef); + } + free(redisRunLoop); + } + return REDIS_ERR; +} + +static void redisMacOSAddRead(void *privdata) { + RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; + CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack); +} + +static void redisMacOSDelRead(void *privdata) { + RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; + CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack); +} + +static void redisMacOSAddWrite(void *privdata) { + RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; + CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack); +} + +static void redisMacOSDelWrite(void *privdata) { + RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; + CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack); +} + +static void redisMacOSCleanup(void *privdata) { + RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata; + freeRedisRunLoop(redisRunLoop); +} + +static void redisMacOSAsyncCallback(CFSocketRef __unused s, CFSocketCallBackType callbackType, CFDataRef __unused address, const void __unused *data, void *info) { + redisAsyncContext* context = (redisAsyncContext*) info; + + switch (callbackType) { + case kCFSocketReadCallBack: + redisAsyncHandleRead(context); + break; + + case kCFSocketWriteCallBack: + redisAsyncHandleWrite(context); + break; + + default: + break; + } +} + +static int redisMacOSAttach(redisAsyncContext *redisAsyncCtx, CFRunLoopRef runLoop) { + redisContext *redisCtx = &(redisAsyncCtx->c); + + /* Nothing should be attached when something is already attached */ + if( redisAsyncCtx->ev.data != NULL ) return REDIS_ERR; + + RedisRunLoop* redisRunLoop = (RedisRunLoop*) calloc(1, sizeof(RedisRunLoop)); + if( !redisRunLoop ) return REDIS_ERR; + + /* Setup redis stuff */ + redisRunLoop->context = redisAsyncCtx; + + redisAsyncCtx->ev.addRead = redisMacOSAddRead; + redisAsyncCtx->ev.delRead = redisMacOSDelRead; + redisAsyncCtx->ev.addWrite = redisMacOSAddWrite; + redisAsyncCtx->ev.delWrite = redisMacOSDelWrite; + redisAsyncCtx->ev.cleanup = redisMacOSCleanup; + redisAsyncCtx->ev.data = redisRunLoop; + + /* Initialize and install read/write events */ + CFSocketContext socketCtx = { 0, redisAsyncCtx, NULL, NULL, NULL }; + + redisRunLoop->socketRef = CFSocketCreateWithNative(NULL, redisCtx->fd, + kCFSocketReadCallBack | kCFSocketWriteCallBack, + redisMacOSAsyncCallback, + &socketCtx); + if( !redisRunLoop->socketRef ) return freeRedisRunLoop(redisRunLoop); + + redisRunLoop->sourceRef = CFSocketCreateRunLoopSource(NULL, redisRunLoop->socketRef, 0); + if( !redisRunLoop->sourceRef ) return freeRedisRunLoop(redisRunLoop); + + CFRunLoopAddSource(runLoop, redisRunLoop->sourceRef, kCFRunLoopDefaultMode); + + return REDIS_OK; +} + +#endif + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/adapters/qt.h new/hiredis-0.13.3/adapters/qt.h --- old/hiredis-0.12.1/adapters/qt.h 1970-01-01 01:00:00.000000000 +0100 +++ new/hiredis-0.13.3/adapters/qt.h 2015-09-16 12:25:02.000000000 +0200 @@ -0,0 +1,135 @@ +/*- + * Copyright (C) 2014 Pietro Cerutti <[email protected]> + * + * 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, this list of conditions and the following disclaimer. + * 2. 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 AUTHOR 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 AUTHOR 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. + */ + +#ifndef __HIREDIS_QT_H__ +#define __HIREDIS_QT_H__ +#include <QSocketNotifier> +#include "../async.h" + +static void RedisQtAddRead(void *); +static void RedisQtDelRead(void *); +static void RedisQtAddWrite(void *); +static void RedisQtDelWrite(void *); +static void RedisQtCleanup(void *); + +class RedisQtAdapter : public QObject { + + Q_OBJECT + + friend + void RedisQtAddRead(void * adapter) { + RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter); + a->addRead(); + } + + friend + void RedisQtDelRead(void * adapter) { + RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter); + a->delRead(); + } + + friend + void RedisQtAddWrite(void * adapter) { + RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter); + a->addWrite(); + } + + friend + void RedisQtDelWrite(void * adapter) { + RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter); + a->delWrite(); + } + + friend + void RedisQtCleanup(void * adapter) { + RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter); + a->cleanup(); + } + + public: + RedisQtAdapter(QObject * parent = 0) + : QObject(parent), m_ctx(0), m_read(0), m_write(0) { } + + ~RedisQtAdapter() { + if (m_ctx != 0) { + m_ctx->ev.data = NULL; + } + } + + int setContext(redisAsyncContext * ac) { + if (ac->ev.data != NULL) { + return REDIS_ERR; + } + m_ctx = ac; + m_ctx->ev.data = this; + m_ctx->ev.addRead = RedisQtAddRead; + m_ctx->ev.delRead = RedisQtDelRead; + m_ctx->ev.addWrite = RedisQtAddWrite; + m_ctx->ev.delWrite = RedisQtDelWrite; + m_ctx->ev.cleanup = RedisQtCleanup; + return REDIS_OK; + } + + private: + void addRead() { + if (m_read) return; + m_read = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Read, 0); + connect(m_read, SIGNAL(activated(int)), this, SLOT(read())); + } + + void delRead() { + if (!m_read) return; + delete m_read; + m_read = 0; + } + + void addWrite() { + if (m_write) return; + m_write = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Write, 0); + connect(m_write, SIGNAL(activated(int)), this, SLOT(write())); + } + + void delWrite() { + if (!m_write) return; + delete m_write; + m_write = 0; + } + + void cleanup() { + delRead(); + delWrite(); + } + + private slots: + void read() { redisAsyncHandleRead(m_ctx); } + void write() { redisAsyncHandleWrite(m_ctx); } + + private: + redisAsyncContext * m_ctx; + QSocketNotifier * m_read; + QSocketNotifier * m_write; +}; + +#endif /* !__HIREDIS_QT_H__ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/async.c new/hiredis-0.13.3/async.c --- old/hiredis-0.12.1/async.c 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/async.c 2015-09-16 12:25:02.000000000 +0200 @@ -418,7 +418,8 @@ if (reply == NULL) { /* When the connection is being disconnected and there are * no more replies, this is the cue to really disconnect. */ - if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0) { + if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0 + && ac->replies.head == NULL) { __redisAsyncDisconnect(ac); return; } @@ -454,6 +455,7 @@ if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) { c->err = REDIS_ERR_OTHER; snprintf(c->errstr,sizeof(c->errstr),"%s",((redisReply*)reply)->str); + c->reader->fn->freeObject(reply); __redisAsyncDisconnect(ac); return; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/examples/example-ivykis.c new/hiredis-0.13.3/examples/example-ivykis.c --- old/hiredis-0.12.1/examples/example-ivykis.c 1970-01-01 01:00:00.000000000 +0100 +++ new/hiredis-0.13.3/examples/example-ivykis.c 2015-09-16 12:25:02.000000000 +0200 @@ -0,0 +1,58 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> + +#include <hiredis.h> +#include <async.h> +#include <adapters/ivykis.h> + +void getCallback(redisAsyncContext *c, void *r, void *privdata) { + redisReply *reply = r; + if (reply == NULL) return; + printf("argv[%s]: %s\n", (char*)privdata, reply->str); + + /* Disconnect after receiving the reply to GET */ + redisAsyncDisconnect(c); +} + +void connectCallback(const redisAsyncContext *c, int status) { + if (status != REDIS_OK) { + printf("Error: %s\n", c->errstr); + return; + } + printf("Connected...\n"); +} + +void disconnectCallback(const redisAsyncContext *c, int status) { + if (status != REDIS_OK) { + printf("Error: %s\n", c->errstr); + return; + } + printf("Disconnected...\n"); +} + +int main (int argc, char **argv) { + signal(SIGPIPE, SIG_IGN); + + iv_init(); + + redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); + if (c->err) { + /* Let *c leak for now... */ + printf("Error: %s\n", c->errstr); + return 1; + } + + redisIvykisAttach(c); + redisAsyncSetConnectCallback(c,connectCallback); + redisAsyncSetDisconnectCallback(c,disconnectCallback); + redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); + redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); + + iv_main(); + + iv_deinit(); + + return 0; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/examples/example-macosx.c new/hiredis-0.13.3/examples/example-macosx.c --- old/hiredis-0.12.1/examples/example-macosx.c 1970-01-01 01:00:00.000000000 +0100 +++ new/hiredis-0.13.3/examples/example-macosx.c 2015-09-16 12:25:02.000000000 +0200 @@ -0,0 +1,66 @@ +// +// Created by Дмитрий Бахвалов on 13.07.15. +// Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved. +// + +#include <stdio.h> + +#include <hiredis.h> +#include <async.h> +#include <adapters/macosx.h> + +void getCallback(redisAsyncContext *c, void *r, void *privdata) { + redisReply *reply = r; + if (reply == NULL) return; + printf("argv[%s]: %s\n", (char*)privdata, reply->str); + + /* Disconnect after receiving the reply to GET */ + redisAsyncDisconnect(c); +} + +void connectCallback(const redisAsyncContext *c, int status) { + if (status != REDIS_OK) { + printf("Error: %s\n", c->errstr); + return; + } + printf("Connected...\n"); +} + +void disconnectCallback(const redisAsyncContext *c, int status) { + if (status != REDIS_OK) { + printf("Error: %s\n", c->errstr); + return; + } + CFRunLoopStop(CFRunLoopGetCurrent()); + printf("Disconnected...\n"); +} + +int main (int argc, char **argv) { + signal(SIGPIPE, SIG_IGN); + + CFRunLoopRef loop = CFRunLoopGetCurrent(); + if( !loop ) { + printf("Error: Cannot get current run loop\n"); + return 1; + } + + redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); + if (c->err) { + /* Let *c leak for now... */ + printf("Error: %s\n", c->errstr); + return 1; + } + + redisMacOSAttach(c, loop); + + redisAsyncSetConnectCallback(c,connectCallback); + redisAsyncSetDisconnectCallback(c,disconnectCallback); + + redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); + redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); + + CFRunLoopRun(); + + return 0; +} + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/examples/example-qt.cpp new/hiredis-0.13.3/examples/example-qt.cpp --- old/hiredis-0.12.1/examples/example-qt.cpp 1970-01-01 01:00:00.000000000 +0100 +++ new/hiredis-0.13.3/examples/example-qt.cpp 2015-09-16 12:25:02.000000000 +0200 @@ -0,0 +1,46 @@ +#include <iostream> +using namespace std; + +#include <QCoreApplication> +#include <QTimer> + +#include "example-qt.h" + +void getCallback(redisAsyncContext *, void * r, void * privdata) { + + redisReply * reply = static_cast<redisReply *>(r); + ExampleQt * ex = static_cast<ExampleQt *>(privdata); + if (reply == nullptr || ex == nullptr) return; + + cout << "key: " << reply->str << endl; + + ex->finish(); +} + +void ExampleQt::run() { + + m_ctx = redisAsyncConnect("localhost", 6379); + + if (m_ctx->err) { + cerr << "Error: " << m_ctx->errstr << endl; + redisAsyncFree(m_ctx); + emit finished(); + } + + m_adapter.setContext(m_ctx); + + redisAsyncCommand(m_ctx, NULL, NULL, "SET key %s", m_value); + redisAsyncCommand(m_ctx, getCallback, this, "GET key"); +} + +int main (int argc, char **argv) { + + QCoreApplication app(argc, argv); + + ExampleQt example(argv[argc-1]); + + QObject::connect(&example, SIGNAL(finished()), &app, SLOT(quit())); + QTimer::singleShot(0, &example, SLOT(run())); + + return app.exec(); +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/examples/example-qt.h new/hiredis-0.13.3/examples/example-qt.h --- old/hiredis-0.12.1/examples/example-qt.h 1970-01-01 01:00:00.000000000 +0100 +++ new/hiredis-0.13.3/examples/example-qt.h 2015-09-16 12:25:02.000000000 +0200 @@ -0,0 +1,32 @@ +#ifndef __HIREDIS_EXAMPLE_QT_H +#define __HIREDIS_EXAMPLE_QT_H + +#include <adapters/qt.h> + +class ExampleQt : public QObject { + + Q_OBJECT + + public: + ExampleQt(const char * value, QObject * parent = 0) + : QObject(parent), m_value(value) {} + + signals: + void finished(); + + public slots: + void run(); + + private: + void finish() { emit finished(); } + + private: + const char * m_value; + redisAsyncContext * m_ctx; + RedisQtAdapter m_adapter; + + friend + void getCallback(redisAsyncContext *, void *, void *); +}; + +#endif /* !__HIREDIS_EXAMPLE_QT_H */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/hiredis.c new/hiredis-0.13.3/hiredis.c --- old/hiredis-0.12.1/hiredis.c 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/hiredis.c 2015-09-16 12:25:02.000000000 +0200 @@ -1,6 +1,8 @@ /* * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com> - * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com> + * Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com> + * Copyright (c) 2015, Matt Stancliff <matt at genges dot com>, + * Jan-Erik Rediger <janerik at fnordig dot com> * * All rights reserved. * @@ -598,6 +600,10 @@ c->errstr[0] = '\0'; c->obuf = sdsempty(); c->reader = redisReaderCreate(); + c->tcp.host = NULL; + c->tcp.source_addr = NULL; + c->unix_sock.path = NULL; + c->timeout = NULL; if (c->obuf == NULL || c->reader == NULL) { redisFree(c); @@ -616,6 +622,14 @@ sdsfree(c->obuf); if (c->reader != NULL) redisReaderFree(c->reader); + if (c->tcp.host) + free(c->tcp.host); + if (c->tcp.source_addr) + free(c->tcp.source_addr); + if (c->unix_sock.path) + free(c->unix_sock.path); + if (c->timeout) + free(c->timeout); free(c); } @@ -626,6 +640,34 @@ return fd; } +int redisReconnect(redisContext *c) { + c->err = 0; + memset(c->errstr, '\0', strlen(c->errstr)); + + if (c->fd > 0) { + close(c->fd); + } + + sdsfree(c->obuf); + redisReaderFree(c->reader); + + c->obuf = sdsempty(); + c->reader = redisReaderCreate(); + + if (c->connection_type == REDIS_CONN_TCP) { + return redisContextConnectBindTcp(c, c->tcp.host, c->tcp.port, + c->timeout, c->tcp.source_addr); + } else if (c->connection_type == REDIS_CONN_UNIX) { + return redisContextConnectUnix(c, c->unix_sock.path, c->timeout); + } else { + /* Something bad happened here and shouldn't have. There isn't + enough information in the context to reconnect. */ + __redisSetError(c,REDIS_ERR_OTHER,"Not enough information to reconnect"); + } + + return REDIS_ERR; +} + /* Connect to a Redis instance. On error the field error in the returned * context will be set to the return value of the error function. * When no set of reply functions is given, the default set will be used. */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/hiredis.h new/hiredis-0.13.3/hiredis.h --- old/hiredis-0.12.1/hiredis.h 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/hiredis.h 2015-09-16 12:25:02.000000000 +0200 @@ -1,6 +1,8 @@ /* * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com> - * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com> + * Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com> + * Copyright (c) 2015, Matt Stancliff <matt at genges dot com>, + * Jan-Erik Rediger <janerik at fnordig dot com> * * All rights reserved. * @@ -38,8 +40,9 @@ #include "sds.h" /* for sds */ #define HIREDIS_MAJOR 0 -#define HIREDIS_MINOR 12 -#define HIREDIS_PATCH 1 +#define HIREDIS_MINOR 13 +#define HIREDIS_PATCH 3 +#define HIREDIS_SONAME 0.13 /* Connection type can be blocking or non-blocking and is set in the * least significant bit of the flags field in redisContext. */ @@ -128,6 +131,11 @@ void redisFreeCommand(char *cmd); void redisFreeSdsCommand(sds cmd); +enum redisConnectionType { + REDIS_CONN_TCP, + REDIS_CONN_UNIX, +}; + /* Context for a connection to Redis */ typedef struct redisContext { int err; /* Error flags, 0 when there is no error */ @@ -136,6 +144,20 @@ int flags; char *obuf; /* Write buffer */ redisReader *reader; /* Protocol reader */ + + enum redisConnectionType connection_type; + struct timeval *timeout; + + struct { + char *host; + char *source_addr; + int port; + } tcp; + + struct { + char *path; + } unix_sock; + } redisContext; redisContext *redisConnect(const char *ip, int port); @@ -149,6 +171,18 @@ redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv); redisContext *redisConnectUnixNonBlock(const char *path); redisContext *redisConnectFd(int fd); + +/** + * Reconnect the given context using the saved information. + * + * This re-uses the exact same connect options as in the initial connection. + * host, ip (or path), timeout and bind address are reused, + * flags are used unmodified from the existing context. + * + * Returns REDIS_OK on successfull connect or REDIS_ERR otherwise. + */ +int redisReconnect(redisContext *c); + int redisSetTimeout(redisContext *c, const struct timeval tv); int redisEnableKeepAlive(redisContext *c); void redisFree(redisContext *c); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/net.c new/hiredis-0.13.3/net.c --- old/hiredis-0.12.1/net.c 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/net.c 2015-09-16 12:25:02.000000000 +0200 @@ -1,7 +1,9 @@ /* Extracted from anet.c to work properly with Hiredis error reporting. * - * Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com> - * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com> + * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com> + * Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com> + * Copyright (c) 2015, Matt Stancliff <matt at genges dot com>, + * Jan-Erik Rediger <janerik at fnordig dot com> * * All rights reserved. * @@ -47,6 +49,7 @@ #include <stdio.h> #include <poll.h> #include <limits.h> +#include <stdlib.h> #include "net.h" #include "sds.h" @@ -263,6 +266,44 @@ int reuseaddr = (c->flags & REDIS_REUSEADDR); int reuses = 0; + c->connection_type = REDIS_CONN_TCP; + c->tcp.port = port; + + /* We need to take possession of the passed parameters + * to make them reusable for a reconnect. + * We also carefully check we don't free data we already own, + * as in the case of the reconnect method. + * + * This is a bit ugly, but atleast it works and doesn't leak memory. + **/ + if (c->tcp.host != addr) { + if (c->tcp.host) + free(c->tcp.host); + + c->tcp.host = strdup(addr); + } + + if (timeout) { + if (c->timeout != timeout) { + if (c->timeout == NULL) + c->timeout = malloc(sizeof(struct timeval)); + + memcpy(c->timeout, timeout, sizeof(struct timeval)); + } + } else { + if (c->timeout) + free(c->timeout); + c->timeout = NULL; + } + + if (source_addr == NULL) { + free(c->tcp.source_addr); + c->tcp.source_addr = NULL; + } else if (c->tcp.source_addr != source_addr) { + free(c->tcp.source_addr); + c->tcp.source_addr = strdup(source_addr); + } + snprintf(_port, 6, "%d", port); memset(&hints,0,sizeof(hints)); hints.ai_family = AF_INET; @@ -273,7 +314,7 @@ * as this would add latency to every connect. Otherwise a more sensible * route could be: Use IPv6 if both addresses are available and there is IPv6 * connectivity. */ - if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { + if ((rv = getaddrinfo(c->tcp.host,_port,&hints,&servinfo)) != 0) { hints.ai_family = AF_INET6; if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) { __redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv)); @@ -288,10 +329,10 @@ c->fd = s; if (redisSetBlocking(c,0) != REDIS_OK) goto error; - if (source_addr) { + if (c->tcp.source_addr) { int bound = 0; /* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */ - if ((rv = getaddrinfo(source_addr, NULL, &hints, &bservinfo)) != 0) { + if ((rv = getaddrinfo(c->tcp.source_addr, NULL, &hints, &bservinfo)) != 0) { char buf[128]; snprintf(buf,sizeof(buf),"Can't get addr: %s",gai_strerror(rv)); __redisSetError(c,REDIS_ERR_OTHER,buf); @@ -333,7 +374,7 @@ goto addrretry; } } else { - if (redisContextWaitReady(c,timeout) != REDIS_OK) + if (redisContextWaitReady(c,c->timeout) != REDIS_OK) goto error; } } @@ -380,13 +421,30 @@ if (redisSetBlocking(c,0) != REDIS_OK) return REDIS_ERR; + c->connection_type = REDIS_CONN_UNIX; + if (c->unix_sock.path != path) + c->unix_sock.path = strdup(path); + + if (timeout) { + if (c->timeout != timeout) { + if (c->timeout == NULL) + c->timeout = malloc(sizeof(struct timeval)); + + memcpy(c->timeout, timeout, sizeof(struct timeval)); + } + } else { + if (c->timeout) + free(c->timeout); + c->timeout = NULL; + } + sa.sun_family = AF_LOCAL; strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1); if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) { if (errno == EINPROGRESS && !blocking) { /* This is ok. */ } else { - if (redisContextWaitReady(c,timeout) != REDIS_OK) + if (redisContextWaitReady(c,c->timeout) != REDIS_OK) return REDIS_ERR; } } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/net.h new/hiredis-0.13.3/net.h --- old/hiredis-0.12.1/net.h 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/net.h 2015-09-16 12:25:02.000000000 +0200 @@ -1,7 +1,9 @@ /* Extracted from anet.c to work properly with Hiredis error reporting. * - * Copyright (c) 2006-2011, Salvatore Sanfilippo <antirez at gmail dot com> - * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com> + * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com> + * Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com> + * Copyright (c) 2015, Matt Stancliff <matt at genges dot com>, + * Jan-Erik Rediger <janerik at fnordig dot com> * * All rights reserved. * diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/read.c new/hiredis-0.13.3/read.c --- old/hiredis-0.12.1/read.c 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/read.c 2015-09-16 12:25:02.000000000 +0200 @@ -33,7 +33,9 @@ #include "fmacros.h" #include <string.h> #include <stdlib.h> +#ifndef _MSC_VER #include <unistd.h> +#endif #include <assert.h> #include <errno.h> #include <ctype.h> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/sds.c new/hiredis-0.13.3/sds.c --- old/hiredis-0.12.1/sds.c 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/sds.c 2015-09-16 12:25:02.000000000 +0200 @@ -103,7 +103,7 @@ * the output will be "6" as the string was modified but the logical length * remains 6 bytes. */ void sdsupdatelen(sds s) { - struct sdshdr *sh = (void*) (s-sizeof *sh);; + struct sdshdr *sh = (void*) (s-sizeof *sh); int reallen = strlen(s); sh->free += (sh->len-reallen); sh->len = reallen; @@ -114,7 +114,7 @@ * so that next append operations will not require allocations up to the * number of bytes previously available. */ void sdsclear(sds s) { - struct sdshdr *sh = (void*) (s-sizeof *sh);; + struct sdshdr *sh = (void*) (s-sizeof *sh); sh->free += sh->len; sh->len = 0; sh->buf[0] = '\0'; @@ -133,7 +133,7 @@ if (free >= addlen) return s; len = sdslen(s); - sh = (void*) (s-sizeof *sh);; + sh = (void*) (s-sizeof *sh); newlen = (len+addlen); if (newlen < SDS_MAX_PREALLOC) newlen *= 2; @@ -155,7 +155,7 @@ sds sdsRemoveFreeSpace(sds s) { struct sdshdr *sh; - sh = (void*) (s-sizeof *sh);; + sh = (void*) (s-sizeof *sh); sh = realloc(sh, sizeof *sh+sh->len+1); sh->free = 0; return sh->buf; @@ -169,7 +169,7 @@ * 4) The implicit null term. */ size_t sdsAllocSize(sds s) { - struct sdshdr *sh = (void*) (s-sizeof *sh);; + struct sdshdr *sh = (void*) (s-sizeof *sh); return sizeof(*sh)+sh->len+sh->free+1; } @@ -198,7 +198,7 @@ * sdsIncrLen(s, nread); */ void sdsIncrLen(sds s, int incr) { - struct sdshdr *sh = (void*) (s-sizeof *sh);; + struct sdshdr *sh = (void*) (s-sizeof *sh); assert(sh->free >= incr); sh->len += incr; @@ -240,7 +240,7 @@ s = sdsMakeRoomFor(s,len); if (s == NULL) return NULL; - sh = (void*) (s-sizeof *sh);; + sh = (void*) (s-sizeof *sh); memcpy(s+curlen, t, len); sh->len = curlen+len; sh->free = sh->free-len; @@ -267,13 +267,13 @@ /* Destructively modify the sds string 's' to hold the specified binary * safe string pointed by 't' of length 'len' bytes. */ sds sdscpylen(sds s, const char *t, size_t len) { - struct sdshdr *sh = (void*) (s-sizeof *sh);; + struct sdshdr *sh = (void*) (s-sizeof *sh); size_t totlen = sh->free+sh->len; if (totlen < len) { s = sdsMakeRoomFor(s,len-sh->len); if (s == NULL) return NULL; - sh = (void*) (s-sizeof *sh);; + sh = (void*) (s-sizeof *sh); totlen = sh->free+sh->len; } memcpy(s, t, len); @@ -541,7 +541,7 @@ * Output will be just "Hello World". */ void sdstrim(sds s, const char *cset) { - struct sdshdr *sh = (void*) (s-sizeof *sh);; + struct sdshdr *sh = (void*) (s-sizeof *sh); char *start, *end, *sp, *ep; size_t len; @@ -573,7 +573,7 @@ * sdsrange(s,1,-1); => "ello World" */ void sdsrange(sds s, int start, int end) { - struct sdshdr *sh = (void*) (s-sizeof *sh);; + struct sdshdr *sh = (void*) (s-sizeof *sh); size_t newlen, len = sdslen(s); if (len == 0) return; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/sds.h new/hiredis-0.13.3/sds.h --- old/hiredis-0.12.1/sds.h 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/sds.h 2015-09-16 12:25:02.000000000 +0200 @@ -35,6 +35,9 @@ #include <sys/types.h> #include <stdarg.h> +#ifdef _MSC_VER +#include "win32.h" +#endif typedef char *sds; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/test.c new/hiredis-0.13.3/test.c --- old/hiredis-0.12.1/test.c 2015-01-26 16:08:40.000000000 +0100 +++ new/hiredis-0.13.3/test.c 2015-09-16 12:25:02.000000000 +0200 @@ -11,6 +11,7 @@ #include <limits.h> #include "hiredis.h" +#include "net.h" enum connection_type { CONN_TCP, @@ -43,6 +44,13 @@ return (((long long)tv.tv_sec)*1000000)+tv.tv_usec; } +/* The assert() calls below have side effects, so we need assert() + * even if we are compiling without asserts (-DNDEBUG). */ +#ifdef NDEBUG +#undef assert +#define assert(e) (void)(e) +#endif + static redisContext *select_database(redisContext *c) { redisReply *reply; @@ -343,6 +351,7 @@ strcmp(c->errstr,"nodename nor servname provided, or not known") == 0 || strcmp(c->errstr,"No address associated with hostname") == 0 || strcmp(c->errstr,"Temporary failure in name resolution") == 0 || + strcmp(c->errstr,"hostname nor servname provided, or not known") == 0 || strcmp(c->errstr,"no address associated with name") == 0)); redisFree(c); @@ -436,6 +445,52 @@ disconnect(c, 0); } +static void test_blocking_connection_timeouts(struct config config) { + redisContext *c; + redisReply *reply; + ssize_t s; + const char *cmd = "DEBUG SLEEP 3\r\n"; + struct timeval tv; + + c = connect(config); + test("Successfully completes a command when the timeout is not exceeded: "); + reply = redisCommand(c,"SET foo fast"); + freeReplyObject(reply); + tv.tv_sec = 0; + tv.tv_usec = 10000; + redisSetTimeout(c, tv); + reply = redisCommand(c, "GET foo"); + test_cond(reply != NULL && reply->type == REDIS_REPLY_STRING && memcmp(reply->str, "fast", 4) == 0); + freeReplyObject(reply); + disconnect(c, 0); + + c = connect(config); + test("Does not return a reply when the command times out: "); + s = write(c->fd, cmd, strlen(cmd)); + tv.tv_sec = 0; + tv.tv_usec = 10000; + redisSetTimeout(c, tv); + reply = redisCommand(c, "GET foo"); + test_cond(s > 0 && reply == NULL && c->err == REDIS_ERR_IO && strcmp(c->errstr, "Resource temporarily unavailable") == 0); + freeReplyObject(reply); + + test("Reconnect properly reconnects after a timeout: "); + redisReconnect(c); + reply = redisCommand(c, "PING"); + test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0); + freeReplyObject(reply); + + test("Reconnect properly uses owned parameters: "); + config.tcp.host = "foo"; + config.unix.path = "foo"; + redisReconnect(c); + reply = redisCommand(c, "PING"); + test_cond(reply != NULL && reply->type == REDIS_REPLY_STATUS && strcmp(reply->str, "PONG") == 0); + freeReplyObject(reply); + + disconnect(c, 0); +} + static void test_blocking_io_errors(struct config config) { redisContext *c; redisReply *reply; @@ -459,7 +514,7 @@ test("Returns I/O error when the connection is lost: "); reply = redisCommand(c,"QUIT"); - if (major >= 2 && minor > 0) { + if (major > 2 || (major == 2 && minor > 0)) { /* > 2.0 returns OK on QUIT and read() should be issued once more * to know the descriptor is at EOF. */ test_cond(strcasecmp(reply->str,"OK") == 0 && @@ -722,6 +777,7 @@ printf("\nTesting against TCP connection (%s:%d):\n", cfg.tcp.host, cfg.tcp.port); cfg.type = CONN_TCP; test_blocking_connection(cfg); + test_blocking_connection_timeouts(cfg); test_blocking_io_errors(cfg); test_invalid_timeout_errors(cfg); test_append_formatted_commands(cfg); @@ -730,6 +786,7 @@ printf("\nTesting against Unix socket connection (%s):\n", cfg.unix.path); cfg.type = CONN_UNIX; test_blocking_connection(cfg); + test_blocking_connection_timeouts(cfg); test_blocking_io_errors(cfg); if (throughput) test_throughput(cfg); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hiredis-0.12.1/win32.h new/hiredis-0.13.3/win32.h --- old/hiredis-0.12.1/win32.h 1970-01-01 01:00:00.000000000 +0100 +++ new/hiredis-0.13.3/win32.h 2015-09-16 12:25:02.000000000 +0200 @@ -0,0 +1,42 @@ +#ifndef _WIN32_HELPER_INCLUDE +#define _WIN32_HELPER_INCLUDE +#ifdef _MSC_VER + +#ifndef inline +#define inline __inline +#endif + +#ifndef va_copy +#define va_copy(d,s) ((d) = (s)) +#endif + +#ifndef snprintf +#define snprintf c99_snprintf + +__inline int c99_vsnprintf(char* str, size_t size, const char* format, va_list ap) +{ + int count = -1; + + if (size != 0) + count = _vsnprintf_s(str, size, _TRUNCATE, format, ap); + if (count == -1) + count = _vscprintf(format, ap); + + return count; +} + +__inline int c99_snprintf(char* str, size_t size, const char* format, ...) +{ + int count; + va_list ap; + + va_start(ap, format); + count = c99_vsnprintf(str, size, format, ap); + va_end(ap); + + return count; +} +#endif + +#endif +#endif \ No newline at end of file
