durable_rules 0.34.57 → 2.00.001
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/librb/durable.rb +46 -28
- data/librb/engine.rb +257 -548
- data/src/rules/Makefile +6 -7
- data/src/rules/events.c +1690 -1559
- data/src/rules/json.h +10 -6
- data/src/rules/rete.c +829 -1046
- data/src/rules/rete.h +66 -52
- data/src/rules/rules.h +67 -109
- data/src/rules/state.c +1245 -449
- data/src/rules/state.h +305 -31
- data/src/rulesrb/extconf.rb +1 -8
- data/src/rulesrb/rules.c +71 -369
- metadata +2 -36
- data/deps/hiredis/COPYING +0 -29
- data/deps/hiredis/Makefile +0 -217
- data/deps/hiredis/async.c +0 -687
- data/deps/hiredis/async.h +0 -129
- data/deps/hiredis/dict.c +0 -338
- data/deps/hiredis/dict.h +0 -126
- data/deps/hiredis/fmacros.h +0 -21
- data/deps/hiredis/hiredis.c +0 -1021
- data/deps/hiredis/hiredis.h +0 -223
- data/deps/hiredis/net.c +0 -458
- data/deps/hiredis/net.h +0 -53
- data/deps/hiredis/read.c +0 -525
- data/deps/hiredis/read.h +0 -116
- data/deps/hiredis/sds.c +0 -1095
- data/deps/hiredis/sds.h +0 -105
- data/deps/hiredis/test.c +0 -807
- data/deps/hiredis/win32.h +0 -42
- data/librb/interface.rb +0 -126
- data/src/rules/net.c +0 -3257
- data/src/rules/net.h +0 -165
data/deps/hiredis/hiredis.h
DELETED
@@ -1,223 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
3
|
-
* Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
4
|
-
* Copyright (c) 2015, Matt Stancliff <matt at genges dot com>,
|
5
|
-
* Jan-Erik Rediger <janerik at fnordig dot com>
|
6
|
-
*
|
7
|
-
* All rights reserved.
|
8
|
-
*
|
9
|
-
* Redistribution and use in source and binary forms, with or without
|
10
|
-
* modification, are permitted provided that the following conditions are met:
|
11
|
-
*
|
12
|
-
* * Redistributions of source code must retain the above copyright notice,
|
13
|
-
* this list of conditions and the following disclaimer.
|
14
|
-
* * Redistributions in binary form must reproduce the above copyright
|
15
|
-
* notice, this list of conditions and the following disclaimer in the
|
16
|
-
* documentation and/or other materials provided with the distribution.
|
17
|
-
* * Neither the name of Redis nor the names of its contributors may be used
|
18
|
-
* to endorse or promote products derived from this software without
|
19
|
-
* specific prior written permission.
|
20
|
-
*
|
21
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
22
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
23
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
24
|
-
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
25
|
-
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
26
|
-
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
27
|
-
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
28
|
-
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
29
|
-
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
30
|
-
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
31
|
-
* POSSIBILITY OF SUCH DAMAGE.
|
32
|
-
*/
|
33
|
-
|
34
|
-
#ifndef __HIREDIS_H
|
35
|
-
#define __HIREDIS_H
|
36
|
-
#include "read.h"
|
37
|
-
#include <stdarg.h> /* for va_list */
|
38
|
-
#include <sys/time.h> /* for struct timeval */
|
39
|
-
#include <stdint.h> /* uintXX_t, etc */
|
40
|
-
#include "sds.h" /* for sds */
|
41
|
-
|
42
|
-
#define HIREDIS_MAJOR 0
|
43
|
-
#define HIREDIS_MINOR 13
|
44
|
-
#define HIREDIS_PATCH 3
|
45
|
-
#define HIREDIS_SONAME 0.13
|
46
|
-
|
47
|
-
/* Connection type can be blocking or non-blocking and is set in the
|
48
|
-
* least significant bit of the flags field in redisContext. */
|
49
|
-
#define REDIS_BLOCK 0x1
|
50
|
-
|
51
|
-
/* Connection may be disconnected before being free'd. The second bit
|
52
|
-
* in the flags field is set when the context is connected. */
|
53
|
-
#define REDIS_CONNECTED 0x2
|
54
|
-
|
55
|
-
/* The async API might try to disconnect cleanly and flush the output
|
56
|
-
* buffer and read all subsequent replies before disconnecting.
|
57
|
-
* This flag means no new commands can come in and the connection
|
58
|
-
* should be terminated once all replies have been read. */
|
59
|
-
#define REDIS_DISCONNECTING 0x4
|
60
|
-
|
61
|
-
/* Flag specific to the async API which means that the context should be clean
|
62
|
-
* up as soon as possible. */
|
63
|
-
#define REDIS_FREEING 0x8
|
64
|
-
|
65
|
-
/* Flag that is set when an async callback is executed. */
|
66
|
-
#define REDIS_IN_CALLBACK 0x10
|
67
|
-
|
68
|
-
/* Flag that is set when the async context has one or more subscriptions. */
|
69
|
-
#define REDIS_SUBSCRIBED 0x20
|
70
|
-
|
71
|
-
/* Flag that is set when monitor mode is active */
|
72
|
-
#define REDIS_MONITORING 0x40
|
73
|
-
|
74
|
-
/* Flag that is set when we should set SO_REUSEADDR before calling bind() */
|
75
|
-
#define REDIS_REUSEADDR 0x80
|
76
|
-
|
77
|
-
#define REDIS_KEEPALIVE_INTERVAL 15 /* seconds */
|
78
|
-
|
79
|
-
/* number of times we retry to connect in the case of EADDRNOTAVAIL and
|
80
|
-
* SO_REUSEADDR is being used. */
|
81
|
-
#define REDIS_CONNECT_RETRIES 10
|
82
|
-
|
83
|
-
/* strerror_r has two completely different prototypes and behaviors
|
84
|
-
* depending on system issues, so we need to operate on the error buffer
|
85
|
-
* differently depending on which strerror_r we're using. */
|
86
|
-
#ifndef _GNU_SOURCE_PLUS
|
87
|
-
/* "regular" POSIX strerror_r that does the right thing. */
|
88
|
-
#define __redis_strerror_r(errno, buf, len) \
|
89
|
-
do { \
|
90
|
-
strerror_r((errno), (buf), (len)); \
|
91
|
-
} while (0)
|
92
|
-
#else
|
93
|
-
/* "bad" GNU strerror_r we need to clean up after. */
|
94
|
-
#define __redis_strerror_r(errno, buf, len) \
|
95
|
-
do { \
|
96
|
-
char *err_str = strerror_r((errno), (buf), (len)); \
|
97
|
-
/* If return value _isn't_ the start of the buffer we passed in, \
|
98
|
-
* then GNU strerror_r returned an internal static buffer and we \
|
99
|
-
* need to copy the result into our private buffer. */ \
|
100
|
-
if (err_str != (buf)) { \
|
101
|
-
buf[(len)] = '\0'; \
|
102
|
-
strncat((buf), err_str, ((len) - 1)); \
|
103
|
-
} \
|
104
|
-
} while (0)
|
105
|
-
#endif
|
106
|
-
|
107
|
-
#ifdef __cplusplus
|
108
|
-
extern "C" {
|
109
|
-
#endif
|
110
|
-
|
111
|
-
/* This is the reply object returned by redisCommand() */
|
112
|
-
typedef struct redisReply {
|
113
|
-
int type; /* REDIS_REPLY_* */
|
114
|
-
long long integer; /* The integer when type is REDIS_REPLY_INTEGER */
|
115
|
-
int len; /* Length of string */
|
116
|
-
char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */
|
117
|
-
size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */
|
118
|
-
struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
|
119
|
-
} redisReply;
|
120
|
-
|
121
|
-
redisReader *redisReaderCreate(void);
|
122
|
-
|
123
|
-
/* Function to free the reply objects hiredis returns by default. */
|
124
|
-
void freeReplyObject(void *reply);
|
125
|
-
|
126
|
-
/* Functions to format a command according to the protocol. */
|
127
|
-
int redisvFormatCommand(char **target, const char *format, va_list ap);
|
128
|
-
int redisFormatCommand(char **target, const char *format, ...);
|
129
|
-
int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen);
|
130
|
-
int redisFormatSdsCommandArgv(sds *target, int argc, const char ** argv, const size_t *argvlen);
|
131
|
-
void redisFreeCommand(char *cmd);
|
132
|
-
void redisFreeSdsCommand(sds cmd);
|
133
|
-
|
134
|
-
enum redisConnectionType {
|
135
|
-
REDIS_CONN_TCP,
|
136
|
-
REDIS_CONN_UNIX,
|
137
|
-
};
|
138
|
-
|
139
|
-
/* Context for a connection to Redis */
|
140
|
-
typedef struct redisContext {
|
141
|
-
int err; /* Error flags, 0 when there is no error */
|
142
|
-
char errstr[128]; /* String representation of error when applicable */
|
143
|
-
int fd;
|
144
|
-
int flags;
|
145
|
-
char *obuf; /* Write buffer */
|
146
|
-
redisReader *reader; /* Protocol reader */
|
147
|
-
|
148
|
-
enum redisConnectionType connection_type;
|
149
|
-
struct timeval *timeout;
|
150
|
-
|
151
|
-
struct {
|
152
|
-
char *host;
|
153
|
-
char *source_addr;
|
154
|
-
int port;
|
155
|
-
} tcp;
|
156
|
-
|
157
|
-
struct {
|
158
|
-
char *path;
|
159
|
-
} unix_sock;
|
160
|
-
|
161
|
-
} redisContext;
|
162
|
-
|
163
|
-
redisContext *redisConnect(const char *ip, int port);
|
164
|
-
redisContext *redisConnectWithTimeout(const char *ip, int port, const struct timeval tv);
|
165
|
-
redisContext *redisConnectNonBlock(const char *ip, int port);
|
166
|
-
redisContext *redisConnectBindNonBlock(const char *ip, int port,
|
167
|
-
const char *source_addr);
|
168
|
-
redisContext *redisConnectBindNonBlockWithReuse(const char *ip, int port,
|
169
|
-
const char *source_addr);
|
170
|
-
redisContext *redisConnectUnix(const char *path);
|
171
|
-
redisContext *redisConnectUnixWithTimeout(const char *path, const struct timeval tv);
|
172
|
-
redisContext *redisConnectUnixNonBlock(const char *path);
|
173
|
-
redisContext *redisConnectFd(int fd);
|
174
|
-
|
175
|
-
/**
|
176
|
-
* Reconnect the given context using the saved information.
|
177
|
-
*
|
178
|
-
* This re-uses the exact same connect options as in the initial connection.
|
179
|
-
* host, ip (or path), timeout and bind address are reused,
|
180
|
-
* flags are used unmodified from the existing context.
|
181
|
-
*
|
182
|
-
* Returns REDIS_OK on successfull connect or REDIS_ERR otherwise.
|
183
|
-
*/
|
184
|
-
int redisReconnect(redisContext *c);
|
185
|
-
|
186
|
-
int redisSetTimeout(redisContext *c, const struct timeval tv);
|
187
|
-
int redisEnableKeepAlive(redisContext *c);
|
188
|
-
void redisFree(redisContext *c);
|
189
|
-
int redisFreeKeepFd(redisContext *c);
|
190
|
-
int redisBufferRead(redisContext *c);
|
191
|
-
int redisBufferWrite(redisContext *c, int *done);
|
192
|
-
|
193
|
-
/* In a blocking context, this function first checks if there are unconsumed
|
194
|
-
* replies to return and returns one if so. Otherwise, it flushes the output
|
195
|
-
* buffer to the socket and reads until it has a reply. In a non-blocking
|
196
|
-
* context, it will return unconsumed replies until there are no more. */
|
197
|
-
int redisGetReply(redisContext *c, void **reply);
|
198
|
-
int redisGetReplyFromReader(redisContext *c, void **reply);
|
199
|
-
|
200
|
-
/* Write a formatted command to the output buffer. Use these functions in blocking mode
|
201
|
-
* to get a pipeline of commands. */
|
202
|
-
int redisAppendFormattedCommand(redisContext *c, const char *cmd, size_t len);
|
203
|
-
|
204
|
-
/* Write a command to the output buffer. Use these functions in blocking mode
|
205
|
-
* to get a pipeline of commands. */
|
206
|
-
int redisvAppendCommand(redisContext *c, const char *format, va_list ap);
|
207
|
-
int redisAppendCommand(redisContext *c, const char *format, ...);
|
208
|
-
int redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
|
209
|
-
|
210
|
-
/* Issue a command to Redis. In a blocking context, it is identical to calling
|
211
|
-
* redisAppendCommand, followed by redisGetReply. The function will return
|
212
|
-
* NULL if there was an error in performing the request, otherwise it will
|
213
|
-
* return the reply. In a non-blocking context, it is identical to calling
|
214
|
-
* only redisAppendCommand and will always return NULL. */
|
215
|
-
void *redisvCommand(redisContext *c, const char *format, va_list ap);
|
216
|
-
void *redisCommand(redisContext *c, const char *format, ...);
|
217
|
-
void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
|
218
|
-
|
219
|
-
#ifdef __cplusplus
|
220
|
-
}
|
221
|
-
#endif
|
222
|
-
|
223
|
-
#endif
|
data/deps/hiredis/net.c
DELETED
@@ -1,458 +0,0 @@
|
|
1
|
-
/* Extracted from anet.c to work properly with Hiredis error reporting.
|
2
|
-
*
|
3
|
-
* Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
|
4
|
-
* Copyright (c) 2010-2014, Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
5
|
-
* Copyright (c) 2015, Matt Stancliff <matt at genges dot com>,
|
6
|
-
* Jan-Erik Rediger <janerik at fnordig dot com>
|
7
|
-
*
|
8
|
-
* All rights reserved.
|
9
|
-
*
|
10
|
-
* Redistribution and use in source and binary forms, with or without
|
11
|
-
* modification, are permitted provided that the following conditions are met:
|
12
|
-
*
|
13
|
-
* * Redistributions of source code must retain the above copyright notice,
|
14
|
-
* this list of conditions and the following disclaimer.
|
15
|
-
* * Redistributions in binary form must reproduce the above copyright
|
16
|
-
* notice, this list of conditions and the following disclaimer in the
|
17
|
-
* documentation and/or other materials provided with the distribution.
|
18
|
-
* * Neither the name of Redis nor the names of its contributors may be used
|
19
|
-
* to endorse or promote products derived from this software without
|
20
|
-
* specific prior written permission.
|
21
|
-
*
|
22
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
-
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
-
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
-
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
-
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
-
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
-
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
-
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
-
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
-
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
-
* POSSIBILITY OF SUCH DAMAGE.
|
33
|
-
*/
|
34
|
-
|
35
|
-
#include "fmacros.h"
|
36
|
-
#include <sys/types.h>
|
37
|
-
#include <sys/socket.h>
|
38
|
-
#include <sys/select.h>
|
39
|
-
#include <sys/un.h>
|
40
|
-
#include <netinet/in.h>
|
41
|
-
#include <netinet/tcp.h>
|
42
|
-
#include <arpa/inet.h>
|
43
|
-
#include <unistd.h>
|
44
|
-
#include <fcntl.h>
|
45
|
-
#include <string.h>
|
46
|
-
#include <netdb.h>
|
47
|
-
#include <errno.h>
|
48
|
-
#include <stdarg.h>
|
49
|
-
#include <stdio.h>
|
50
|
-
#include <poll.h>
|
51
|
-
#include <limits.h>
|
52
|
-
#include <stdlib.h>
|
53
|
-
|
54
|
-
#include "net.h"
|
55
|
-
#include "sds.h"
|
56
|
-
|
57
|
-
/* Defined in hiredis.c */
|
58
|
-
void __redisSetError(redisContext *c, int type, const char *str);
|
59
|
-
|
60
|
-
static void redisContextCloseFd(redisContext *c) {
|
61
|
-
if (c && c->fd >= 0) {
|
62
|
-
close(c->fd);
|
63
|
-
c->fd = -1;
|
64
|
-
}
|
65
|
-
}
|
66
|
-
|
67
|
-
static void __redisSetErrorFromErrno(redisContext *c, int type, const char *prefix) {
|
68
|
-
char buf[128] = { 0 };
|
69
|
-
size_t len = 0;
|
70
|
-
|
71
|
-
if (prefix != NULL)
|
72
|
-
len = snprintf(buf,sizeof(buf),"%s: ",prefix);
|
73
|
-
//__redis_strerror_r(errno, (char *)(buf + len), sizeof(buf) - len);
|
74
|
-
__redisSetError(c,type,buf);
|
75
|
-
}
|
76
|
-
|
77
|
-
static int redisSetReuseAddr(redisContext *c) {
|
78
|
-
int on = 1;
|
79
|
-
if (setsockopt(c->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
|
80
|
-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
81
|
-
redisContextCloseFd(c);
|
82
|
-
return REDIS_ERR;
|
83
|
-
}
|
84
|
-
return REDIS_OK;
|
85
|
-
}
|
86
|
-
|
87
|
-
static int redisCreateSocket(redisContext *c, int type) {
|
88
|
-
int s;
|
89
|
-
if ((s = socket(type, SOCK_STREAM, 0)) == -1) {
|
90
|
-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
91
|
-
return REDIS_ERR;
|
92
|
-
}
|
93
|
-
c->fd = s;
|
94
|
-
if (type == AF_INET) {
|
95
|
-
if (redisSetReuseAddr(c) == REDIS_ERR) {
|
96
|
-
return REDIS_ERR;
|
97
|
-
}
|
98
|
-
}
|
99
|
-
return REDIS_OK;
|
100
|
-
}
|
101
|
-
|
102
|
-
static int redisSetBlocking(redisContext *c, int blocking) {
|
103
|
-
int flags;
|
104
|
-
|
105
|
-
/* Set the socket nonblocking.
|
106
|
-
* Note that fcntl(2) for F_GETFL and F_SETFL can't be
|
107
|
-
* interrupted by a signal. */
|
108
|
-
if ((flags = fcntl(c->fd, F_GETFL)) == -1) {
|
109
|
-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_GETFL)");
|
110
|
-
redisContextCloseFd(c);
|
111
|
-
return REDIS_ERR;
|
112
|
-
}
|
113
|
-
|
114
|
-
if (blocking)
|
115
|
-
flags &= ~O_NONBLOCK;
|
116
|
-
else
|
117
|
-
flags |= O_NONBLOCK;
|
118
|
-
|
119
|
-
if (fcntl(c->fd, F_SETFL, flags) == -1) {
|
120
|
-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"fcntl(F_SETFL)");
|
121
|
-
redisContextCloseFd(c);
|
122
|
-
return REDIS_ERR;
|
123
|
-
}
|
124
|
-
return REDIS_OK;
|
125
|
-
}
|
126
|
-
|
127
|
-
int redisKeepAlive(redisContext *c, int interval) {
|
128
|
-
int val = 1;
|
129
|
-
int fd = c->fd;
|
130
|
-
|
131
|
-
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){
|
132
|
-
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
133
|
-
return REDIS_ERR;
|
134
|
-
}
|
135
|
-
|
136
|
-
val = interval;
|
137
|
-
|
138
|
-
#ifdef _OSX
|
139
|
-
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val)) < 0) {
|
140
|
-
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
141
|
-
return REDIS_ERR;
|
142
|
-
}
|
143
|
-
#else
|
144
|
-
#if defined(__GLIBC__) && !defined(__FreeBSD_kernel__)
|
145
|
-
val = interval;
|
146
|
-
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val)) < 0) {
|
147
|
-
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
148
|
-
return REDIS_ERR;
|
149
|
-
}
|
150
|
-
|
151
|
-
val = interval/3;
|
152
|
-
if (val == 0) val = 1;
|
153
|
-
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val)) < 0) {
|
154
|
-
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
155
|
-
return REDIS_ERR;
|
156
|
-
}
|
157
|
-
|
158
|
-
val = 3;
|
159
|
-
if (setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val)) < 0) {
|
160
|
-
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
161
|
-
return REDIS_ERR;
|
162
|
-
}
|
163
|
-
#endif
|
164
|
-
#endif
|
165
|
-
|
166
|
-
return REDIS_OK;
|
167
|
-
}
|
168
|
-
|
169
|
-
static int redisSetTcpNoDelay(redisContext *c) {
|
170
|
-
int yes = 1;
|
171
|
-
if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
|
172
|
-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(TCP_NODELAY)");
|
173
|
-
redisContextCloseFd(c);
|
174
|
-
return REDIS_ERR;
|
175
|
-
}
|
176
|
-
return REDIS_OK;
|
177
|
-
}
|
178
|
-
|
179
|
-
#define __MAX_MSEC (((LONG_MAX) - 999) / 1000)
|
180
|
-
|
181
|
-
static int redisContextWaitReady(redisContext *c, const struct timeval *timeout) {
|
182
|
-
struct pollfd wfd[1];
|
183
|
-
long msec;
|
184
|
-
|
185
|
-
msec = -1;
|
186
|
-
wfd[0].fd = c->fd;
|
187
|
-
wfd[0].events = POLLOUT;
|
188
|
-
|
189
|
-
/* Only use timeout when not NULL. */
|
190
|
-
if (timeout != NULL) {
|
191
|
-
if (timeout->tv_usec > 1000000 || timeout->tv_sec > __MAX_MSEC) {
|
192
|
-
__redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL);
|
193
|
-
redisContextCloseFd(c);
|
194
|
-
return REDIS_ERR;
|
195
|
-
}
|
196
|
-
|
197
|
-
msec = (timeout->tv_sec * 1000) + ((timeout->tv_usec + 999) / 1000);
|
198
|
-
|
199
|
-
if (msec < 0 || msec > INT_MAX) {
|
200
|
-
msec = INT_MAX;
|
201
|
-
}
|
202
|
-
}
|
203
|
-
|
204
|
-
if (errno == EINPROGRESS) {
|
205
|
-
int res;
|
206
|
-
|
207
|
-
if ((res = poll(wfd, 1, msec)) == -1) {
|
208
|
-
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
|
209
|
-
redisContextCloseFd(c);
|
210
|
-
return REDIS_ERR;
|
211
|
-
} else if (res == 0) {
|
212
|
-
errno = ETIMEDOUT;
|
213
|
-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
214
|
-
redisContextCloseFd(c);
|
215
|
-
return REDIS_ERR;
|
216
|
-
}
|
217
|
-
|
218
|
-
if (redisCheckSocketError(c) != REDIS_OK)
|
219
|
-
return REDIS_ERR;
|
220
|
-
|
221
|
-
return REDIS_OK;
|
222
|
-
}
|
223
|
-
|
224
|
-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
225
|
-
redisContextCloseFd(c);
|
226
|
-
return REDIS_ERR;
|
227
|
-
}
|
228
|
-
|
229
|
-
int redisCheckSocketError(redisContext *c) {
|
230
|
-
int err = 0;
|
231
|
-
socklen_t errlen = sizeof(err);
|
232
|
-
|
233
|
-
if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
|
234
|
-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"getsockopt(SO_ERROR)");
|
235
|
-
return REDIS_ERR;
|
236
|
-
}
|
237
|
-
|
238
|
-
if (err) {
|
239
|
-
errno = err;
|
240
|
-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
241
|
-
return REDIS_ERR;
|
242
|
-
}
|
243
|
-
|
244
|
-
return REDIS_OK;
|
245
|
-
}
|
246
|
-
|
247
|
-
int redisContextSetTimeout(redisContext *c, const struct timeval tv) {
|
248
|
-
if (setsockopt(c->fd,SOL_SOCKET,SO_RCVTIMEO,&tv,sizeof(tv)) == -1) {
|
249
|
-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_RCVTIMEO)");
|
250
|
-
return REDIS_ERR;
|
251
|
-
}
|
252
|
-
if (setsockopt(c->fd,SOL_SOCKET,SO_SNDTIMEO,&tv,sizeof(tv)) == -1) {
|
253
|
-
__redisSetErrorFromErrno(c,REDIS_ERR_IO,"setsockopt(SO_SNDTIMEO)");
|
254
|
-
return REDIS_ERR;
|
255
|
-
}
|
256
|
-
return REDIS_OK;
|
257
|
-
}
|
258
|
-
|
259
|
-
static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
|
260
|
-
const struct timeval *timeout,
|
261
|
-
const char *source_addr) {
|
262
|
-
int s, rv, n;
|
263
|
-
char _port[6]; /* strlen("65535"); */
|
264
|
-
struct addrinfo hints, *servinfo, *bservinfo, *p, *b;
|
265
|
-
int blocking = (c->flags & REDIS_BLOCK);
|
266
|
-
int reuseaddr = (c->flags & REDIS_REUSEADDR);
|
267
|
-
int reuses = 0;
|
268
|
-
|
269
|
-
c->connection_type = REDIS_CONN_TCP;
|
270
|
-
c->tcp.port = port;
|
271
|
-
|
272
|
-
/* We need to take possession of the passed parameters
|
273
|
-
* to make them reusable for a reconnect.
|
274
|
-
* We also carefully check we don't free data we already own,
|
275
|
-
* as in the case of the reconnect method.
|
276
|
-
*
|
277
|
-
* This is a bit ugly, but atleast it works and doesn't leak memory.
|
278
|
-
**/
|
279
|
-
if (c->tcp.host != addr) {
|
280
|
-
if (c->tcp.host)
|
281
|
-
free(c->tcp.host);
|
282
|
-
|
283
|
-
c->tcp.host = strdup(addr);
|
284
|
-
}
|
285
|
-
|
286
|
-
if (timeout) {
|
287
|
-
if (c->timeout != timeout) {
|
288
|
-
if (c->timeout == NULL)
|
289
|
-
c->timeout = malloc(sizeof(struct timeval));
|
290
|
-
|
291
|
-
memcpy(c->timeout, timeout, sizeof(struct timeval));
|
292
|
-
}
|
293
|
-
} else {
|
294
|
-
if (c->timeout)
|
295
|
-
free(c->timeout);
|
296
|
-
c->timeout = NULL;
|
297
|
-
}
|
298
|
-
|
299
|
-
if (source_addr == NULL) {
|
300
|
-
free(c->tcp.source_addr);
|
301
|
-
c->tcp.source_addr = NULL;
|
302
|
-
} else if (c->tcp.source_addr != source_addr) {
|
303
|
-
free(c->tcp.source_addr);
|
304
|
-
c->tcp.source_addr = strdup(source_addr);
|
305
|
-
}
|
306
|
-
|
307
|
-
snprintf(_port, 6, "%d", port);
|
308
|
-
memset(&hints,0,sizeof(hints));
|
309
|
-
hints.ai_family = AF_INET;
|
310
|
-
hints.ai_socktype = SOCK_STREAM;
|
311
|
-
|
312
|
-
/* Try with IPv6 if no IPv4 address was found. We do it in this order since
|
313
|
-
* in a Redis client you can't afford to test if you have IPv6 connectivity
|
314
|
-
* as this would add latency to every connect. Otherwise a more sensible
|
315
|
-
* route could be: Use IPv6 if both addresses are available and there is IPv6
|
316
|
-
* connectivity. */
|
317
|
-
if ((rv = getaddrinfo(c->tcp.host,_port,&hints,&servinfo)) != 0) {
|
318
|
-
hints.ai_family = AF_INET6;
|
319
|
-
if ((rv = getaddrinfo(addr,_port,&hints,&servinfo)) != 0) {
|
320
|
-
__redisSetError(c,REDIS_ERR_OTHER,gai_strerror(rv));
|
321
|
-
return REDIS_ERR;
|
322
|
-
}
|
323
|
-
}
|
324
|
-
for (p = servinfo; p != NULL; p = p->ai_next) {
|
325
|
-
addrretry:
|
326
|
-
if ((s = socket(p->ai_family,p->ai_socktype,p->ai_protocol)) == -1)
|
327
|
-
continue;
|
328
|
-
|
329
|
-
c->fd = s;
|
330
|
-
if (redisSetBlocking(c,0) != REDIS_OK)
|
331
|
-
goto error;
|
332
|
-
if (c->tcp.source_addr) {
|
333
|
-
int bound = 0;
|
334
|
-
/* Using getaddrinfo saves us from self-determining IPv4 vs IPv6 */
|
335
|
-
if ((rv = getaddrinfo(c->tcp.source_addr, NULL, &hints, &bservinfo)) != 0) {
|
336
|
-
char buf[128];
|
337
|
-
snprintf(buf,sizeof(buf),"Can't get addr: %s",gai_strerror(rv));
|
338
|
-
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
339
|
-
goto error;
|
340
|
-
}
|
341
|
-
|
342
|
-
if (reuseaddr) {
|
343
|
-
n = 1;
|
344
|
-
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*) &n,
|
345
|
-
sizeof(n)) < 0) {
|
346
|
-
goto error;
|
347
|
-
}
|
348
|
-
}
|
349
|
-
|
350
|
-
for (b = bservinfo; b != NULL; b = b->ai_next) {
|
351
|
-
if (bind(s,b->ai_addr,b->ai_addrlen) != -1) {
|
352
|
-
bound = 1;
|
353
|
-
break;
|
354
|
-
}
|
355
|
-
}
|
356
|
-
freeaddrinfo(bservinfo);
|
357
|
-
if (!bound) {
|
358
|
-
char buf[128];
|
359
|
-
snprintf(buf,sizeof(buf),"Can't bind socket: %s",strerror(errno));
|
360
|
-
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
361
|
-
goto error;
|
362
|
-
}
|
363
|
-
}
|
364
|
-
if (connect(s,p->ai_addr,p->ai_addrlen) == -1) {
|
365
|
-
if (errno == EHOSTUNREACH) {
|
366
|
-
redisContextCloseFd(c);
|
367
|
-
continue;
|
368
|
-
} else if (errno == EINPROGRESS && !blocking) {
|
369
|
-
/* This is ok. */
|
370
|
-
} else if (errno == EADDRNOTAVAIL && reuseaddr) {
|
371
|
-
if (++reuses >= REDIS_CONNECT_RETRIES) {
|
372
|
-
goto error;
|
373
|
-
} else {
|
374
|
-
goto addrretry;
|
375
|
-
}
|
376
|
-
} else {
|
377
|
-
if (redisContextWaitReady(c,c->timeout) != REDIS_OK)
|
378
|
-
goto error;
|
379
|
-
}
|
380
|
-
}
|
381
|
-
if (blocking && redisSetBlocking(c,1) != REDIS_OK)
|
382
|
-
goto error;
|
383
|
-
if (redisSetTcpNoDelay(c) != REDIS_OK)
|
384
|
-
goto error;
|
385
|
-
|
386
|
-
c->flags |= REDIS_CONNECTED;
|
387
|
-
rv = REDIS_OK;
|
388
|
-
goto end;
|
389
|
-
}
|
390
|
-
if (p == NULL) {
|
391
|
-
char buf[128];
|
392
|
-
snprintf(buf,sizeof(buf),"Can't create socket: %s",strerror(errno));
|
393
|
-
__redisSetError(c,REDIS_ERR_OTHER,buf);
|
394
|
-
goto error;
|
395
|
-
}
|
396
|
-
|
397
|
-
error:
|
398
|
-
rv = REDIS_ERR;
|
399
|
-
end:
|
400
|
-
freeaddrinfo(servinfo);
|
401
|
-
return rv; // Need to return REDIS_OK if alright
|
402
|
-
}
|
403
|
-
|
404
|
-
int redisContextConnectTcp(redisContext *c, const char *addr, int port,
|
405
|
-
const struct timeval *timeout) {
|
406
|
-
return _redisContextConnectTcp(c, addr, port, timeout, NULL);
|
407
|
-
}
|
408
|
-
|
409
|
-
int redisContextConnectBindTcp(redisContext *c, const char *addr, int port,
|
410
|
-
const struct timeval *timeout,
|
411
|
-
const char *source_addr) {
|
412
|
-
return _redisContextConnectTcp(c, addr, port, timeout, source_addr);
|
413
|
-
}
|
414
|
-
|
415
|
-
int redisContextConnectUnix(redisContext *c, const char *path, const struct timeval *timeout) {
|
416
|
-
int blocking = (c->flags & REDIS_BLOCK);
|
417
|
-
struct sockaddr_un sa;
|
418
|
-
|
419
|
-
if (redisCreateSocket(c,AF_LOCAL) < 0)
|
420
|
-
return REDIS_ERR;
|
421
|
-
if (redisSetBlocking(c,0) != REDIS_OK)
|
422
|
-
return REDIS_ERR;
|
423
|
-
|
424
|
-
c->connection_type = REDIS_CONN_UNIX;
|
425
|
-
if (c->unix_sock.path != path)
|
426
|
-
c->unix_sock.path = strdup(path);
|
427
|
-
|
428
|
-
if (timeout) {
|
429
|
-
if (c->timeout != timeout) {
|
430
|
-
if (c->timeout == NULL)
|
431
|
-
c->timeout = malloc(sizeof(struct timeval));
|
432
|
-
|
433
|
-
memcpy(c->timeout, timeout, sizeof(struct timeval));
|
434
|
-
}
|
435
|
-
} else {
|
436
|
-
if (c->timeout)
|
437
|
-
free(c->timeout);
|
438
|
-
c->timeout = NULL;
|
439
|
-
}
|
440
|
-
|
441
|
-
sa.sun_family = AF_LOCAL;
|
442
|
-
strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
|
443
|
-
if (connect(c->fd, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
|
444
|
-
if (errno == EINPROGRESS && !blocking) {
|
445
|
-
/* This is ok. */
|
446
|
-
} else {
|
447
|
-
if (redisContextWaitReady(c,c->timeout) != REDIS_OK)
|
448
|
-
return REDIS_ERR;
|
449
|
-
}
|
450
|
-
}
|
451
|
-
|
452
|
-
/* Reset socket to be blocking after connect(2). */
|
453
|
-
if (blocking && redisSetBlocking(c,1) != REDIS_OK)
|
454
|
-
return REDIS_ERR;
|
455
|
-
|
456
|
-
c->flags |= REDIS_CONNECTED;
|
457
|
-
return REDIS_OK;
|
458
|
-
}
|