| /* |
| * 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. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * * Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * * Neither the name of Redis nor the names of its contributors may be used |
| * to endorse or promote products derived from this software without |
| * specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 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_H |
| #define __HIREDIS_H |
| #include "read.h" |
| #include <stdarg.h> /* for va_list */ |
| #include <sys/time.h> /* for struct timeval */ |
| #include <stdint.h> /* uintXX_t, etc */ |
| #include "sds.h" /* for sds */ |
| |
| #define HIREDIS_MAJOR 0 |
| #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. */ |
| #define REDIS_BLOCK 0x1 |
| |
| /* Connection may be disconnected before being free'd. The second bit |
| * in the flags field is set when the context is connected. */ |
| #define REDIS_CONNECTED 0x2 |
| |
| /* The async API might try to disconnect cleanly and flush the output |
| * buffer and read all subsequent replies before disconnecting. |
| * This flag means no new commands can come in and the connection |
| * should be terminated once all replies have been read. */ |
| #define REDIS_DISCONNECTING 0x4 |
| |
| /* Flag specific to the async API which means that the context should be clean |
| * up as soon as possible. */ |
| #define REDIS_FREEING 0x8 |
| |
| /* Flag that is set when an async callback is executed. */ |
| #define REDIS_IN_CALLBACK 0x10 |
| |
| /* Flag that is set when the async context has one or more subscriptions. */ |
| #define REDIS_SUBSCRIBED 0x20 |
| |
| /* Flag that is set when monitor mode is active */ |
| #define REDIS_MONITORING 0x40 |
| |
| /* Flag that is set when we should set SO_REUSEADDR before calling bind() */ |
| #define REDIS_REUSEADDR 0x80 |
| |
| #define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */ |
| |
| /* number of times we retry to connect in the case of EADDRNOTAVAIL and |
| * SO_REUSEADDR is being used. */ |
| #define REDIS_CONNECT_RETRIES 10 |
| |
| /* strerror_r has two completely different prototypes and behaviors |
| * depending on system issues, so we need to operate on the error buffer |
| * differently depending on which strerror_r we're using. */ |
| #ifndef _GNU_SOURCE |
| /* "regular" POSIX strerror_r that does the right thing. */ |
| #define __redis_strerror_r(errno, buf, len) \ |
| do { \ |
| strerror_r((errno), (buf), (len)); \ |
| } while (0) |
| #else |
| /* "bad" GNU strerror_r we need to clean up after. */ |
| #define __redis_strerror_r(errno, buf, len) \ |
| do { \ |
| char *err_str = strerror_r((errno), (buf), (len)); \ |
| /* If return value _isn't_ the start of the buffer we passed in, \ |
| * then GNU strerror_r returned an internal static buffer and we \ |
| * need to copy the result into our private buffer. */ \ |
| if (err_str != (buf)) { \ |
| strncpy((buf), err_str, ((len) - 1)); \ |
| buf[(len)-1] = '\0'; \ |
| } \ |
| } while (0) |
| #endif |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /* This is the reply object returned by redisCommand() */ |
| typedef struct redisReply { |
| int type; /* REDIS_REPLY_* */ |
| long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ |
| size_t len; /* Length of string */ |
| char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */ |
| size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */ |
| struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */ |
| } redisReply; |
| |
| redisReader *redisReaderCreate(void); |
| |
| /* Function to free the reply objects hiredis returns by default. */ |
| void freeReplyObject(void *reply); |
| |
| /* Functions to format a command according to the protocol. */ |
| int redisvFormatCommand(char **target, const char *format, va_list ap); |
| int redisFormatCommand(char **target, const char *format, ...); |
| int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen); |
| int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen); |
| 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 */ |
| char errstr[128]; /* String representation of error when applicable */ |
| int fd; |
| 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); |
| redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv); |
| redisContext *redisConnectNonBlock(const char *ip, int port); |
| redisContext *redisConnectBindNonBlock(const char *ip, int port, |
| const char *source_addr); |
| redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port, |
| const char *source_addr); |
| redisContext *redisConnectUnix(const char *path); |
| 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 successful 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); |
| int redisFreeKeepFd(redisContext *c); |
| int redisBufferRead(redisContext *c); |
| int redisBufferWrite(redisContext *c, int *done); |
| |
| /* 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 |
| * buffer to the socket and reads until it has a reply. In a non-blocking |
| * context, it will return unconsumed replies until there are no more. */ |
| int redisGetReply(redisContext *c, void **reply); |
| int redisGetReplyFromReader(redisContext *c, void **reply); |
| |
| /* Write a formatted command to the output buffer. Use these functions in blocking mode |
| * to get a pipeline of commands. */ |
| int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len); |
| |
| /* Write a command to the output buffer. Use these functions in blocking mode |
| * to get a pipeline of commands. */ |
| int redisvAppendCommand(redisContext *c, const char *format, va_list ap); |
| int redisAppendCommand(redisContext *c, const char *format, ...); |
| int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); |
| |
| /* Issue a command to Redis. In a blocking context, it is identical to calling |
| * redisAppendCommand, followed by redisGetReply. The function will return |
| * NULL if there was an error in performing the request, otherwise it will |
| * return the reply. In a non-blocking context, it is identical to calling |
| * only redisAppendCommand and will always return NULL. */ |
| void *redisvCommand(redisContext *c, const char *format, va_list ap); |
| void *redisCommand(redisContext *c, const char *format, ...); |
| void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen); |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif |