├── .gitignore ├── .travis.yml ├── LICENSE ├── Makefile ├── README.md ├── examples └── basic_example.c ├── redispool.c └── redispool.h /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Libraries 12 | *.lib 13 | *.a 14 | *.la 15 | *.lo 16 | 17 | # Shared objects (inc. Windows DLLs) 18 | *.dll 19 | *.so 20 | *.so.* 21 | *.dylib 22 | 23 | # Executables 24 | *.exe 25 | *.out 26 | *.app 27 | *.i*86 28 | *.x86_64 29 | *.hex 30 | 31 | # Debug files 32 | *.dSYM/ 33 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | sudo: false 3 | branches: 4 | only: 5 | - master 6 | compiler: 7 | - clang 8 | - gcc 9 | 10 | addons: 11 | apt: 12 | packages: 13 | - libhiredis-dev 14 | install: 15 | - if [ $TRAVIS_OS_NAME = linux ]; then 16 | git clone https://github.com/msempere/redispool.git; 17 | cd redispool; 18 | make; 19 | sudo make install; 20 | cd ..; 21 | fi 22 | env: 23 | - CFLAGS="-Werror" 24 | script: make $TARGET CFLAGS="$CFLAGS" && make $TARGET_VARS redispool-example 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 MSempere 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | OBJ=redispool.o 2 | LIBNAME=libredispool 3 | EXAMPLES=redispool-example 4 | 5 | REDISPOOL_MAJOR=$(shell grep REDISPOOL_MAJOR redispool.h | awk '{print $$3}') 6 | REDISPOOL_MINOR=$(shell grep REDISPOOL_MINOR redispool.h | awk '{print $$3}') 7 | REDISPOOL_SONAME=$(shell grep REDISPOOL_SONAME redispool.h | awk '{print $$3}') 8 | 9 | PREFIX?=/usr/local 10 | INCLUDE_PATH?=include/redispool 11 | LIBRARY_PATH?=lib 12 | INSTALL_INCLUDE_PATH= $(DESTDIR)$(PREFIX)/$(INCLUDE_PATH) 13 | INSTALL_LIBRARY_PATH= $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH) 14 | 15 | # Fallback to gcc when $CC is not in $PATH. 16 | CC:=LD_LIBRARY_PATH=/usr/local/lib/ $(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc') 17 | CXX:=$(shell sh -c 'type $(CXX) >/dev/null 2>/dev/null && echo $(CXX) || echo g++') 18 | OPTIMIZATION?=-O3 19 | WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings 20 | DEBUG?= -g -ggdb 21 | REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG) $(ARCH) 22 | REAL_LDFLAGS=$(LDFLAGS) $(ARCH) 23 | 24 | DYLIBSUFFIX=so 25 | STLIBSUFFIX=a 26 | DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(REDISPOOL_SONAME) 27 | DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(REDISPOOL_MAJOR) 28 | DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX) 29 | DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS) 30 | STLIBNAME=$(LIBNAME).$(STLIBSUFFIX) 31 | STLIB_MAKE_CMD=ar rcs $(STLIBNAME) 32 | 33 | 34 | # Platform-specific overrides 35 | uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') 36 | ifeq ($(uname_S),SunOS) 37 | REAL_LDFLAGS+= -ldl -lnsl -lsocket 38 | DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS) 39 | INSTALL= cp -r 40 | endif 41 | ifeq ($(uname_S),Darwin) 42 | DYLIBSUFFIX=dylib 43 | DYLIB_MINOR_NAME=$(LIBNAME).$(REDISPOOL_SONAME).$(DYLIBSUFFIX) 44 | DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS) 45 | endif 46 | 47 | all: $(DYLIBNAME) $(STLIBNAME) 48 | 49 | redispool.o: redispool.c redispool.h 50 | 51 | $(DYLIBNAME): $(OBJ) 52 | $(DYLIB_MAKE_CMD) $(OBJ) 53 | 54 | $(STLIBNAME): $(OBJ) 55 | $(STLIB_MAKE_CMD) $(OBJ) 56 | 57 | dynamic: $(DYLIBNAME) 58 | static: $(STLIBNAME) 59 | 60 | redispool-example: examples/basic_example.c $(STLIBNAME) 61 | $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(STLIBNAME) -lhiredis 62 | 63 | examples: $(EXAMPLES) 64 | 65 | hiredis: 66 | git clone https://github.com/redis/hiredis.git 67 | cd hiredis && make && sudo make install 68 | 69 | redispool-%: %.o $(STLIBNAME) 70 | $(CC) $(REAL_CFLAGS) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME) 71 | 72 | .c.o: 73 | $(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $< 74 | 75 | clean: 76 | rm -rf $(DYLIBNAME) $(STLIBNAME) *.o 77 | 78 | dep: 79 | $(CC) -MM *.c 80 | 81 | ifeq ($(uname_S),SunOS) 82 | INSTALL?= cp -r 83 | endif 84 | 85 | INSTALL?= cp -a 86 | 87 | install: $(DYLIBNAME) $(STLIBNAME) 88 | mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH) 89 | $(INSTALL) redispool.h $(INSTALL_INCLUDE_PATH) 90 | $(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME) 91 | cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIBNAME) 92 | $(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH) 93 | 94 | .PHONY: all clean dep install 95 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![alt logo](http://i.imgur.com/0yz70i0.png?1) 2 | # RedisPool [![alt build](https://travis-ci.org/msempere/redispool.svg?branch=master)](https://travis-ci.org/msempere/redispool) 3 | Connection pool for Redis 4 | 5 | ### Dependencies 6 | RedisPool requires hiredis only 7 | 8 | ### Install 9 | Installing hiredis, on a Debian system: 10 | ``` 11 | sudo apt-get install libhiredis-dev 12 | ``` 13 | 14 | Or manually: 15 | ``` 16 | git clone https://github.com/redis/hiredis.git 17 | cd hiredis & make & make install 18 | ``` 19 | 20 | Or using makefile from RedisPool: 21 | ``` 22 | make hiredis 23 | ``` 24 | 25 | Installing RedisPool: 26 | ``` 27 | git clone https://github.com/msempere/redispool.git 28 | cd redispool & make & make install 29 | ``` 30 | 31 | ### License 32 | Distributed under MIT license. See `LICENSE` for more information. 33 | -------------------------------------------------------------------------------- /examples/basic_example.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(void){ 5 | 6 | const char *hostname = "127.0.0.1"; 7 | int port = 6379; 8 | struct timeval timeout = { 1, 500000 }; // 1.5 seconds 9 | 10 | redisConnectionPool *pool; 11 | pool = redisCreateConnectionPool(5, hostname, port, timeout); 12 | printf("Connections: %d\n", redisConnectionsInConnectionPool(pool)); 13 | 14 | redisContext *connection; 15 | 16 | connection = redisConnectWithTimeout(hostname, port, timeout); 17 | if (connection == NULL || connection->err) { 18 | if (connection) { 19 | printf("Connection error: %s\n", connection->errstr); 20 | redisFree(connection); 21 | } else { 22 | printf("Connection error: can't allocate redis context\n"); 23 | } 24 | } 25 | 26 | redisPutConnectionInConnectionPool(connection, pool); 27 | printf("Connections: %d\n", redisConnectionsInConnectionPool(pool)); 28 | 29 | connection = redisGetConnectionFromConnectionPool(pool); 30 | printf("Connections: %d\n", redisConnectionsInConnectionPool(pool)); 31 | 32 | if(connection != NULL){ 33 | redisReply *reply; 34 | reply = redisCommand(connection,"PING"); 35 | printf("PING: %s\n", reply->str); 36 | freeReplyObject(reply); 37 | } 38 | redisFreeConnectionPool(pool); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /redispool.c: -------------------------------------------------------------------------------- 1 | #include "redispool.h" 2 | #include 3 | 4 | static redisConnectionPool *redisConnectionPoolInit( 5 | int size, 6 | const char *hostname, 7 | int port, 8 | struct timeval timeout){ 9 | redisConnectionPool *c; 10 | c = calloc(1, sizeof(redisConnectionPool)); 11 | 12 | if (c == NULL) 13 | return NULL; 14 | 15 | c->hostname = hostname; 16 | c->port = port; 17 | c->timeout = timeout; 18 | c->connections = malloc(sizeof(redisContext*) * size); 19 | 20 | if (c->connections == NULL) 21 | return NULL; 22 | 23 | c->allowedConnections = size; 24 | c->usedConnections = 0; 25 | 26 | return c; 27 | } 28 | 29 | redisConnectionPool *redisCreateConnectionPool( 30 | int size, 31 | const char *hostname, 32 | int port, 33 | struct timeval timeout){ 34 | return redisConnectionPoolInit(size, hostname, port, timeout); 35 | } 36 | 37 | void redisFreeConnectionPool(redisConnectionPool *pool){ 38 | if(pool != NULL && pool->connections != NULL){ 39 | if(pool->usedConnections > 0){ 40 | int i = 0; 41 | for(; iusedConnections; i++){ 42 | if(pool->connections[i] != NULL){ 43 | redisFree(pool->connections[i]); 44 | pool->connections[i] = NULL; 45 | } 46 | } 47 | } 48 | free(pool->connections); 49 | pool->connections = NULL; 50 | } 51 | } 52 | 53 | redisContext *redisGetConnectionFromConnectionPool(redisConnectionPool *pool){ 54 | if(pool != NULL && pool->connections != NULL ){ 55 | if(pool->usedConnections > 0){ 56 | redisContext *c; 57 | pthread_mutex_lock(&pool->lock); 58 | c = pool->connections[pool->usedConnections - 1]; 59 | pool->connections[pool->usedConnections - 1] = NULL; 60 | pool->usedConnections--; 61 | pthread_mutex_unlock(&pool->lock); 62 | return c; 63 | } 64 | else{ 65 | return redisConnectWithTimeout(pool->hostname, pool->port, pool->timeout); 66 | } 67 | } 68 | else { 69 | return NULL; 70 | } 71 | } 72 | 73 | void redisPutConnectionInConnectionPool(redisContext *c, redisConnectionPool *pool){ 74 | if(c != NULL && pool != NULL && !c->err && pool->connections != NULL 75 | && pool->usedConnections < pool->allowedConnections){ 76 | pthread_mutex_lock(&pool->lock); 77 | pool->connections[pool->usedConnections] = c; 78 | pool->usedConnections++; 79 | pthread_mutex_unlock(&pool->lock); 80 | } 81 | } 82 | 83 | int redisConnectionsInConnectionPool(redisConnectionPool *pool){ 84 | return pool->usedConnections; 85 | } 86 | 87 | int redisConnectionPoolDepth(redisConnectionPool *pool){ 88 | return pool->allowedConnections; 89 | } 90 | -------------------------------------------------------------------------------- /redispool.h: -------------------------------------------------------------------------------- 1 | #ifndef __REDIS_CONNECTION_POOL_H 2 | #define __REDIS_CONNECTION_POOL_H 3 | 4 | #include 5 | #include 6 | 7 | #define REDISPOOL_MAJOR 0 8 | #define REDISPOOL_MINOR 1 9 | #define REDISPOOL_SONAME 0.1 10 | 11 | typedef struct redisConnectionPool { 12 | redisContext **connections; 13 | int allowedConnections; 14 | int usedConnections; 15 | pthread_mutex_t lock; 16 | const char *hostname; 17 | int port; 18 | struct timeval timeout; 19 | } redisConnectionPool; 20 | 21 | void redisFreeConnectionPool(redisConnectionPool *pool); 22 | 23 | redisConnectionPool *redisCreateConnectionPool(int size, const char *hostname, int port, struct timeval timeout); 24 | 25 | void redisPutConnectionInConnectionPool(redisContext *c, redisConnectionPool *pool); 26 | 27 | redisContext *redisGetConnectionFromConnectionPool(redisConnectionPool *pool); 28 | 29 | int redisConnectionsInConnectionPool(redisConnectionPool *pool); 30 | 31 | int redisConnectionPoolDepth(redisConnectionPool *pool); 32 | 33 | #endif 34 | --------------------------------------------------------------------------------