Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
3ddb6ffa
Commit
3ddb6ffa
authored
Aug 06, 2020
by
michael-grunder
Browse files
Remove hiredis so we can add it as a subtree
parent
c17e597d
Changes
53
Show whitespace changes
Inline
Side-by-side
deps/hiredis/dict.h
deleted
100644 → 0
View file @
c17e597d
/* Hash table implementation.
*
* This file implements in memory hash tables with insert/del/replace/find/
* get-random-element operations. Hash tables will auto resize if needed
* tables of power of two in size are used, collisions are handled by
* chaining. See the source code for more information... :)
*
* Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail 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 __DICT_H
#define __DICT_H
#define DICT_OK 0
#define DICT_ERR 1
/* Unused arguments generate annoying warnings... */
#define DICT_NOTUSED(V) ((void) V)
typedef
struct
dictEntry
{
void
*
key
;
void
*
val
;
struct
dictEntry
*
next
;
}
dictEntry
;
typedef
struct
dictType
{
unsigned
int
(
*
hashFunction
)(
const
void
*
key
);
void
*
(
*
keyDup
)(
void
*
privdata
,
const
void
*
key
);
void
*
(
*
valDup
)(
void
*
privdata
,
const
void
*
obj
);
int
(
*
keyCompare
)(
void
*
privdata
,
const
void
*
key1
,
const
void
*
key2
);
void
(
*
keyDestructor
)(
void
*
privdata
,
void
*
key
);
void
(
*
valDestructor
)(
void
*
privdata
,
void
*
obj
);
}
dictType
;
typedef
struct
dict
{
dictEntry
**
table
;
dictType
*
type
;
unsigned
long
size
;
unsigned
long
sizemask
;
unsigned
long
used
;
void
*
privdata
;
}
dict
;
typedef
struct
dictIterator
{
dict
*
ht
;
int
index
;
dictEntry
*
entry
,
*
nextEntry
;
}
dictIterator
;
/* This is the initial size of every hash table */
#define DICT_HT_INITIAL_SIZE 4
/* ------------------------------- Macros ------------------------------------*/
#define dictFreeEntryVal(ht, entry) \
if ((ht)->type->valDestructor) \
(ht)->type->valDestructor((ht)->privdata, (entry)->val)
#define dictSetHashVal(ht, entry, _val_) do { \
if ((ht)->type->valDup) \
entry->val = (ht)->type->valDup((ht)->privdata, _val_); \
else \
entry->val = (_val_); \
} while(0)
#define dictFreeEntryKey(ht, entry) \
if ((ht)->type->keyDestructor) \
(ht)->type->keyDestructor((ht)->privdata, (entry)->key)
#define dictSetHashKey(ht, entry, _key_) do { \
if ((ht)->type->keyDup) \
entry->key = (ht)->type->keyDup((ht)->privdata, _key_); \
else \
entry->key = (_key_); \
} while(0)
#define dictCompareHashKeys(ht, key1, key2) \
(((ht)->type->keyCompare) ? \
(ht)->type->keyCompare((ht)->privdata, key1, key2) : \
(key1) == (key2))
#define dictHashKey(ht, key) (ht)->type->hashFunction(key)
#define dictGetEntryKey(he) ((he)->key)
#define dictGetEntryVal(he) ((he)->val)
#define dictSlots(ht) ((ht)->size)
#define dictSize(ht) ((ht)->used)
/* API */
static
unsigned
int
dictGenHashFunction
(
const
unsigned
char
*
buf
,
int
len
);
static
dict
*
dictCreate
(
dictType
*
type
,
void
*
privDataPtr
);
static
int
dictExpand
(
dict
*
ht
,
unsigned
long
size
);
static
int
dictAdd
(
dict
*
ht
,
void
*
key
,
void
*
val
);
static
int
dictReplace
(
dict
*
ht
,
void
*
key
,
void
*
val
);
static
int
dictDelete
(
dict
*
ht
,
const
void
*
key
);
static
void
dictRelease
(
dict
*
ht
);
static
dictEntry
*
dictFind
(
dict
*
ht
,
const
void
*
key
);
static
dictIterator
*
dictGetIterator
(
dict
*
ht
);
static
dictEntry
*
dictNext
(
dictIterator
*
iter
);
static
void
dictReleaseIterator
(
dictIterator
*
iter
);
#endif
/* __DICT_H */
deps/hiredis/examples/CMakeLists.txt
deleted
100644 → 0
View file @
c17e597d
INCLUDE
(
FindPkgConfig
)
# Check for GLib
PKG_CHECK_MODULES
(
GLIB2 glib-2.0
)
if
(
GLIB2_FOUND
)
INCLUDE_DIRECTORIES
(
${
GLIB2_INCLUDE_DIRS
}
)
LINK_DIRECTORIES
(
${
GLIB2_LIBRARY_DIRS
}
)
ADD_EXECUTABLE
(
example-glib example-glib.c
)
TARGET_LINK_LIBRARIES
(
example-glib hiredis
${
GLIB2_LIBRARIES
}
)
ENDIF
(
GLIB2_FOUND
)
FIND_PATH
(
LIBEV ev.h
HINTS /usr/local /usr/opt/local
ENV LIBEV_INCLUDE_DIR
)
if
(
LIBEV
)
# Just compile and link with libev
ADD_EXECUTABLE
(
example-libev example-libev.c
)
TARGET_LINK_LIBRARIES
(
example-libev hiredis ev
)
ENDIF
()
FIND_PATH
(
LIBEVENT event.h
)
if
(
LIBEVENT
)
ADD_EXECUTABLE
(
example-libevent example-libevent
)
TARGET_LINK_LIBRARIES
(
example-libevent hiredis event
)
ENDIF
()
FIND_PATH
(
LIBUV uv.h
)
IF
(
LIBUV
)
ADD_EXECUTABLE
(
example-libuv example-libuv.c
)
TARGET_LINK_LIBRARIES
(
example-libuv hiredis uv
)
ENDIF
()
IF
(
APPLE
)
FIND_LIBRARY
(
CF CoreFoundation
)
ADD_EXECUTABLE
(
example-macosx example-macosx.c
)
TARGET_LINK_LIBRARIES
(
example-macosx hiredis
${
CF
}
)
ENDIF
()
IF
(
ENABLE_SSL
)
ADD_EXECUTABLE
(
example-ssl example-ssl.c
)
TARGET_LINK_LIBRARIES
(
example-ssl hiredis hiredis_ssl
)
ENDIF
()
ADD_EXECUTABLE
(
example example.c
)
TARGET_LINK_LIBRARIES
(
example hiredis
)
deps/hiredis/examples/example-ae.c
deleted
100644 → 0
View file @
c17e597d
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <hiredis.h>
#include <async.h>
#include <adapters/ae.h>
/* Put event loop in the global scope, so it can be explicitly stopped */
static
aeEventLoop
*
loop
;
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
);
aeStop
(
loop
);
return
;
}
printf
(
"Connected...
\n
"
);
}
void
disconnectCallback
(
const
redisAsyncContext
*
c
,
int
status
)
{
if
(
status
!=
REDIS_OK
)
{
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
aeStop
(
loop
);
return
;
}
printf
(
"Disconnected...
\n
"
);
aeStop
(
loop
);
}
int
main
(
int
argc
,
char
**
argv
)
{
signal
(
SIGPIPE
,
SIG_IGN
);
redisAsyncContext
*
c
=
redisAsyncConnect
(
"127.0.0.1"
,
6379
);
if
(
c
->
err
)
{
/* Let *c leak for now... */
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
return
1
;
}
loop
=
aeCreateEventLoop
(
64
);
redisAeAttach
(
loop
,
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"
);
aeMain
(
loop
);
return
0
;
}
deps/hiredis/examples/example-glib.c
deleted
100644 → 0
View file @
c17e597d
#include <stdlib.h>
#include <hiredis.h>
#include <async.h>
#include <adapters/glib.h>
static
GMainLoop
*
mainloop
;
static
void
connect_cb
(
const
redisAsyncContext
*
ac
G_GNUC_UNUSED
,
int
status
)
{
if
(
status
!=
REDIS_OK
)
{
g_printerr
(
"Failed to connect: %s
\n
"
,
ac
->
errstr
);
g_main_loop_quit
(
mainloop
);
}
else
{
g_printerr
(
"Connected...
\n
"
);
}
}
static
void
disconnect_cb
(
const
redisAsyncContext
*
ac
G_GNUC_UNUSED
,
int
status
)
{
if
(
status
!=
REDIS_OK
)
{
g_error
(
"Failed to disconnect: %s"
,
ac
->
errstr
);
}
else
{
g_printerr
(
"Disconnected...
\n
"
);
g_main_loop_quit
(
mainloop
);
}
}
static
void
command_cb
(
redisAsyncContext
*
ac
,
gpointer
r
,
gpointer
user_data
G_GNUC_UNUSED
)
{
redisReply
*
reply
=
r
;
if
(
reply
)
{
g_print
(
"REPLY: %s
\n
"
,
reply
->
str
);
}
redisAsyncDisconnect
(
ac
);
}
gint
main
(
gint
argc
G_GNUC_UNUSED
,
gchar
*
argv
[]
G_GNUC_UNUSED
)
{
redisAsyncContext
*
ac
;
GMainContext
*
context
=
NULL
;
GSource
*
source
;
ac
=
redisAsyncConnect
(
"127.0.0.1"
,
6379
);
if
(
ac
->
err
)
{
g_printerr
(
"%s
\n
"
,
ac
->
errstr
);
exit
(
EXIT_FAILURE
);
}
source
=
redis_source_new
(
ac
);
mainloop
=
g_main_loop_new
(
context
,
FALSE
);
g_source_attach
(
source
,
context
);
redisAsyncSetConnectCallback
(
ac
,
connect_cb
);
redisAsyncSetDisconnectCallback
(
ac
,
disconnect_cb
);
redisAsyncCommand
(
ac
,
command_cb
,
NULL
,
"SET key 1234"
);
redisAsyncCommand
(
ac
,
command_cb
,
NULL
,
"GET key"
);
g_main_loop_run
(
mainloop
);
return
EXIT_SUCCESS
;
}
deps/hiredis/examples/example-ivykis.c
deleted
100644 → 0
View file @
c17e597d
#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
;
}
deps/hiredis/examples/example-libev.c
deleted
100644 → 0
View file @
c17e597d
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <hiredis.h>
#include <async.h>
#include <adapters/libev.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
);
redisAsyncContext
*
c
=
redisAsyncConnect
(
"127.0.0.1"
,
6379
);
if
(
c
->
err
)
{
/* Let *c leak for now... */
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
return
1
;
}
redisLibevAttach
(
EV_DEFAULT_
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"
);
ev_loop
(
EV_DEFAULT_
0
);
return
0
;
}
deps/hiredis/examples/example-libevent-ssl.c
deleted
100644 → 0
View file @
c17e597d
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <hiredis.h>
#include <hiredis_ssl.h>
#include <async.h>
#include <adapters/libevent.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
);
struct
event_base
*
base
=
event_base_new
();
if
(
argc
<
5
)
{
fprintf
(
stderr
,
"Usage: %s <key> <host> <port> <cert> <certKey> [ca]
\n
"
,
argv
[
0
]);
exit
(
1
);
}
const
char
*
value
=
argv
[
1
];
size_t
nvalue
=
strlen
(
value
);
const
char
*
hostname
=
argv
[
2
];
int
port
=
atoi
(
argv
[
3
]);
const
char
*
cert
=
argv
[
4
];
const
char
*
certKey
=
argv
[
5
];
const
char
*
caCert
=
argc
>
5
?
argv
[
6
]
:
NULL
;
redisAsyncContext
*
c
=
redisAsyncConnect
(
hostname
,
port
);
if
(
c
->
err
)
{
/* Let *c leak for now... */
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
return
1
;
}
if
(
redisSecureConnection
(
&
c
->
c
,
caCert
,
cert
,
certKey
,
"sni"
)
!=
REDIS_OK
)
{
printf
(
"SSL Error!
\n
"
);
exit
(
1
);
}
redisLibeventAttach
(
c
,
base
);
redisAsyncSetConnectCallback
(
c
,
connectCallback
);
redisAsyncSetDisconnectCallback
(
c
,
disconnectCallback
);
redisAsyncCommand
(
c
,
NULL
,
NULL
,
"SET key %b"
,
value
,
nvalue
);
redisAsyncCommand
(
c
,
getCallback
,
(
char
*
)
"end-1"
,
"GET key"
);
event_base_dispatch
(
base
);
return
0
;
}
deps/hiredis/examples/example-libevent.c
deleted
100644 → 0
View file @
c17e597d
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <hiredis.h>
#include <async.h>
#include <adapters/libevent.h>
void
getCallback
(
redisAsyncContext
*
c
,
void
*
r
,
void
*
privdata
)
{
redisReply
*
reply
=
r
;
if
(
reply
==
NULL
)
{
if
(
c
->
errstr
)
{
printf
(
"errstr: %s
\n
"
,
c
->
errstr
);
}
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
);
struct
event_base
*
base
=
event_base_new
();
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
"127.0.0.1"
,
6379
);
struct
timeval
tv
=
{
0
};
tv
.
tv_sec
=
1
;
options
.
timeout
=
&
tv
;
redisAsyncContext
*
c
=
redisAsyncConnectWithOptions
(
&
options
);
if
(
c
->
err
)
{
/* Let *c leak for now... */
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
return
1
;
}
redisLibeventAttach
(
c
,
base
);
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"
);
event_base_dispatch
(
base
);
return
0
;
}
deps/hiredis/examples/example-libuv.c
deleted
100644 → 0
View file @
c17e597d
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <hiredis.h>
#include <async.h>
#include <adapters/libuv.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
);
uv_loop_t
*
loop
=
uv_default_loop
();
redisAsyncContext
*
c
=
redisAsyncConnect
(
"127.0.0.1"
,
6379
);
if
(
c
->
err
)
{
/* Let *c leak for now... */
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
return
1
;
}
redisLibuvAttach
(
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"
);
uv_run
(
loop
,
UV_RUN_DEFAULT
);
return
0
;
}
deps/hiredis/examples/example-macosx.c
deleted
100644 → 0
View file @
c17e597d
//
// 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
;
}
deps/hiredis/examples/example-qt.cpp
deleted
100644 → 0
View file @
c17e597d
#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
();
}
deps/hiredis/examples/example-qt.h
deleted
100644 → 0
View file @
c17e597d
#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 */
deps/hiredis/examples/example-ssl.c
deleted
100644 → 0
View file @
c17e597d
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hiredis.h>
#include <hiredis_ssl.h>
int
main
(
int
argc
,
char
**
argv
)
{
unsigned
int
j
;
redisContext
*
c
;
redisReply
*
reply
;
if
(
argc
<
4
)
{
printf
(
"Usage: %s <host> <port> <cert> <key> [ca]
\n
"
,
argv
[
0
]);
exit
(
1
);
}
const
char
*
hostname
=
(
argc
>
1
)
?
argv
[
1
]
:
"127.0.0.1"
;
int
port
=
atoi
(
argv
[
2
]);
const
char
*
cert
=
argv
[
3
];
const
char
*
key
=
argv
[
4
];
const
char
*
ca
=
argc
>
4
?
argv
[
5
]
:
NULL
;
struct
timeval
tv
=
{
1
,
500000
};
// 1.5 seconds
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
hostname
,
port
);
options
.
timeout
=
&
tv
;
c
=
redisConnectWithOptions
(
&
options
);
if
(
c
==
NULL
||
c
->
err
)
{
if
(
c
)
{
printf
(
"Connection error: %s
\n
"
,
c
->
errstr
);
redisFree
(
c
);
}
else
{
printf
(
"Connection error: can't allocate redis context
\n
"
);
}
exit
(
1
);
}
if
(
redisSecureConnection
(
c
,
ca
,
cert
,
key
,
"sni"
)
!=
REDIS_OK
)
{
printf
(
"Couldn't initialize SSL!
\n
"
);
printf
(
"Error: %s
\n
"
,
c
->
errstr
);
redisFree
(
c
);
exit
(
1
);
}
/* PING server */
reply
=
redisCommand
(
c
,
"PING"
);
printf
(
"PING: %s
\n
"
,
reply
->
str
);
freeReplyObject
(
reply
);
/* Set a key */
reply
=
redisCommand
(
c
,
"SET %s %s"
,
"foo"
,
"hello world"
);
printf
(
"SET: %s
\n
"
,
reply
->
str
);
freeReplyObject
(
reply
);
/* Set a key using binary safe API */
reply
=
redisCommand
(
c
,
"SET %b %b"
,
"bar"
,
(
size_t
)
3
,
"hello"
,
(
size_t
)
5
);
printf
(
"SET (binary API): %s
\n
"
,
reply
->
str
);
freeReplyObject
(
reply
);
/* Try a GET and two INCR */
reply
=
redisCommand
(
c
,
"GET foo"
);
printf
(
"GET foo: %s
\n
"
,
reply
->
str
);
freeReplyObject
(
reply
);
reply
=
redisCommand
(
c
,
"INCR counter"
);
printf
(
"INCR counter: %lld
\n
"
,
reply
->
integer
);
freeReplyObject
(
reply
);
/* again ... */
reply
=
redisCommand
(
c
,
"INCR counter"
);
printf
(
"INCR counter: %lld
\n
"
,
reply
->
integer
);
freeReplyObject
(
reply
);
/* Create a list of numbers, from 0 to 9 */
reply
=
redisCommand
(
c
,
"DEL mylist"
);
freeReplyObject
(
reply
);
for
(
j
=
0
;
j
<
10
;
j
++
)
{
char
buf
[
64
];
snprintf
(
buf
,
64
,
"%u"
,
j
);
reply
=
redisCommand
(
c
,
"LPUSH mylist element-%s"
,
buf
);
freeReplyObject
(
reply
);
}
/* Let's check what we have inside the list */
reply
=
redisCommand
(
c
,
"LRANGE mylist 0 -1"
);
if
(
reply
->
type
==
REDIS_REPLY_ARRAY
)
{
for
(
j
=
0
;
j
<
reply
->
elements
;
j
++
)
{
printf
(
"%u) %s
\n
"
,
j
,
reply
->
element
[
j
]
->
str
);
}
}
freeReplyObject
(
reply
);
/* Disconnects and frees the context */
redisFree
(
c
);
return
0
;
}
deps/hiredis/examples/example.c
deleted
100644 → 0
View file @
c17e597d
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hiredis.h>
int
main
(
int
argc
,
char
**
argv
)
{
unsigned
int
j
,
isunix
=
0
;
redisContext
*
c
;
redisReply
*
reply
;
const
char
*
hostname
=
(
argc
>
1
)
?
argv
[
1
]
:
"127.0.0.1"
;
if
(
argc
>
2
)
{
if
(
*
argv
[
2
]
==
'u'
||
*
argv
[
2
]
==
'U'
)
{
isunix
=
1
;
/* in this case, host is the path to the unix socket */
printf
(
"Will connect to unix socket @%s
\n
"
,
hostname
);
}
}
int
port
=
(
argc
>
2
)
?
atoi
(
argv
[
2
])
:
6379
;
struct
timeval
timeout
=
{
1
,
500000
};
// 1.5 seconds
if
(
isunix
)
{
c
=
redisConnectUnixWithTimeout
(
hostname
,
timeout
);
}
else
{
c
=
redisConnectWithTimeout
(
hostname
,
port
,
timeout
);
}
if
(
c
==
NULL
||
c
->
err
)
{
if
(
c
)
{
printf
(
"Connection error: %s
\n
"
,
c
->
errstr
);
redisFree
(
c
);
}
else
{
printf
(
"Connection error: can't allocate redis context
\n
"
);
}
exit
(
1
);
}
/* PING server */
reply
=
redisCommand
(
c
,
"PING"
);
printf
(
"PING: %s
\n
"
,
reply
->
str
);
freeReplyObject
(
reply
);
/* Set a key */
reply
=
redisCommand
(
c
,
"SET %s %s"
,
"foo"
,
"hello world"
);
printf
(
"SET: %s
\n
"
,
reply
->
str
);
freeReplyObject
(
reply
);
/* Set a key using binary safe API */
reply
=
redisCommand
(
c
,
"SET %b %b"
,
"bar"
,
(
size_t
)
3
,
"hello"
,
(
size_t
)
5
);
printf
(
"SET (binary API): %s
\n
"
,
reply
->
str
);
freeReplyObject
(
reply
);
/* Try a GET and two INCR */
reply
=
redisCommand
(
c
,
"GET foo"
);
printf
(
"GET foo: %s
\n
"
,
reply
->
str
);
freeReplyObject
(
reply
);
reply
=
redisCommand
(
c
,
"INCR counter"
);
printf
(
"INCR counter: %lld
\n
"
,
reply
->
integer
);
freeReplyObject
(
reply
);
/* again ... */
reply
=
redisCommand
(
c
,
"INCR counter"
);
printf
(
"INCR counter: %lld
\n
"
,
reply
->
integer
);
freeReplyObject
(
reply
);
/* Create a list of numbers, from 0 to 9 */
reply
=
redisCommand
(
c
,
"DEL mylist"
);
freeReplyObject
(
reply
);
for
(
j
=
0
;
j
<
10
;
j
++
)
{
char
buf
[
64
];
snprintf
(
buf
,
64
,
"%u"
,
j
);
reply
=
redisCommand
(
c
,
"LPUSH mylist element-%s"
,
buf
);
freeReplyObject
(
reply
);
}
/* Let's check what we have inside the list */
reply
=
redisCommand
(
c
,
"LRANGE mylist 0 -1"
);
if
(
reply
->
type
==
REDIS_REPLY_ARRAY
)
{
for
(
j
=
0
;
j
<
reply
->
elements
;
j
++
)
{
printf
(
"%u) %s
\n
"
,
j
,
reply
->
element
[
j
]
->
str
);
}
}
freeReplyObject
(
reply
);
/* Disconnects and frees the context */
redisFree
(
c
);
return
0
;
}
deps/hiredis/fmacros.h
deleted
100644 → 0
View file @
c17e597d
#ifndef __HIREDIS_FMACRO_H
#define __HIREDIS_FMACRO_H
#define _XOPEN_SOURCE 600
#define _POSIX_C_SOURCE 200112L
#if defined(__APPLE__) && defined(__MACH__)
/* Enable TCP_KEEPALIVE */
#define _DARWIN_C_SOURCE
#endif
#endif
deps/hiredis/hiredis.c
deleted
100644 → 0
View file @
c17e597d
/*
* 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.
*/
#include "fmacros.h"
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <ctype.h>
#include "hiredis.h"
#include "net.h"
#include "sds.h"
#include "async.h"
#include "win32.h"
static
redisContextFuncs
redisContextDefaultFuncs
=
{
.
free_privdata
=
NULL
,
.
async_read
=
redisAsyncRead
,
.
async_write
=
redisAsyncWrite
,
.
read
=
redisNetRead
,
.
write
=
redisNetWrite
};
static
redisReply
*
createReplyObject
(
int
type
);
static
void
*
createStringObject
(
const
redisReadTask
*
task
,
char
*
str
,
size_t
len
);
static
void
*
createArrayObject
(
const
redisReadTask
*
task
,
size_t
elements
);
static
void
*
createIntegerObject
(
const
redisReadTask
*
task
,
long
long
value
);
static
void
*
createDoubleObject
(
const
redisReadTask
*
task
,
double
value
,
char
*
str
,
size_t
len
);
static
void
*
createNilObject
(
const
redisReadTask
*
task
);
static
void
*
createBoolObject
(
const
redisReadTask
*
task
,
int
bval
);
/* Default set of functions to build the reply. Keep in mind that such a
* function returning NULL is interpreted as OOM. */
static
redisReplyObjectFunctions
defaultFunctions
=
{
createStringObject
,
createArrayObject
,
createIntegerObject
,
createDoubleObject
,
createNilObject
,
createBoolObject
,
freeReplyObject
};
/* Create a reply object */
static
redisReply
*
createReplyObject
(
int
type
)
{
redisReply
*
r
=
calloc
(
1
,
sizeof
(
*
r
));
if
(
r
==
NULL
)
return
NULL
;
r
->
type
=
type
;
return
r
;
}
/* Free a reply object */
void
freeReplyObject
(
void
*
reply
)
{
redisReply
*
r
=
reply
;
size_t
j
;
if
(
r
==
NULL
)
return
;
switch
(
r
->
type
)
{
case
REDIS_REPLY_INTEGER
:
break
;
/* Nothing to free */
case
REDIS_REPLY_ARRAY
:
case
REDIS_REPLY_MAP
:
case
REDIS_REPLY_SET
:
if
(
r
->
element
!=
NULL
)
{
for
(
j
=
0
;
j
<
r
->
elements
;
j
++
)
freeReplyObject
(
r
->
element
[
j
]);
free
(
r
->
element
);
}
break
;
case
REDIS_REPLY_ERROR
:
case
REDIS_REPLY_STATUS
:
case
REDIS_REPLY_STRING
:
case
REDIS_REPLY_DOUBLE
:
free
(
r
->
str
);
break
;
}
free
(
r
);
}
static
void
*
createStringObject
(
const
redisReadTask
*
task
,
char
*
str
,
size_t
len
)
{
redisReply
*
r
,
*
parent
;
char
*
buf
;
r
=
createReplyObject
(
task
->
type
);
if
(
r
==
NULL
)
return
NULL
;
assert
(
task
->
type
==
REDIS_REPLY_ERROR
||
task
->
type
==
REDIS_REPLY_STATUS
||
task
->
type
==
REDIS_REPLY_STRING
||
task
->
type
==
REDIS_REPLY_VERB
);
/* Copy string value */
if
(
task
->
type
==
REDIS_REPLY_VERB
)
{
buf
=
malloc
(
len
-
4
+
1
);
/* Skip 4 bytes of verbatim type header. */
if
(
buf
==
NULL
)
{
freeReplyObject
(
r
);
return
NULL
;
}
memcpy
(
r
->
vtype
,
str
,
3
);
r
->
vtype
[
3
]
=
'\0'
;
memcpy
(
buf
,
str
+
4
,
len
-
4
);
buf
[
len
-
4
]
=
'\0'
;
r
->
len
=
len
-
4
;
}
else
{
buf
=
malloc
(
len
+
1
);
if
(
buf
==
NULL
)
{
freeReplyObject
(
r
);
return
NULL
;
}
memcpy
(
buf
,
str
,
len
);
buf
[
len
]
=
'\0'
;
r
->
len
=
len
;
}
r
->
str
=
buf
;
if
(
task
->
parent
)
{
parent
=
task
->
parent
->
obj
;
assert
(
parent
->
type
==
REDIS_REPLY_ARRAY
||
parent
->
type
==
REDIS_REPLY_MAP
||
parent
->
type
==
REDIS_REPLY_SET
);
parent
->
element
[
task
->
idx
]
=
r
;
}
return
r
;
}
static
void
*
createArrayObject
(
const
redisReadTask
*
task
,
size_t
elements
)
{
redisReply
*
r
,
*
parent
;
r
=
createReplyObject
(
task
->
type
);
if
(
r
==
NULL
)
return
NULL
;
if
(
elements
>
0
)
{
r
->
element
=
calloc
(
elements
,
sizeof
(
redisReply
*
));
if
(
r
->
element
==
NULL
)
{
freeReplyObject
(
r
);
return
NULL
;
}
}
r
->
elements
=
elements
;
if
(
task
->
parent
)
{
parent
=
task
->
parent
->
obj
;
assert
(
parent
->
type
==
REDIS_REPLY_ARRAY
||
parent
->
type
==
REDIS_REPLY_MAP
||
parent
->
type
==
REDIS_REPLY_SET
);
parent
->
element
[
task
->
idx
]
=
r
;
}
return
r
;
}
static
void
*
createIntegerObject
(
const
redisReadTask
*
task
,
long
long
value
)
{
redisReply
*
r
,
*
parent
;
r
=
createReplyObject
(
REDIS_REPLY_INTEGER
);
if
(
r
==
NULL
)
return
NULL
;
r
->
integer
=
value
;
if
(
task
->
parent
)
{
parent
=
task
->
parent
->
obj
;
assert
(
parent
->
type
==
REDIS_REPLY_ARRAY
||
parent
->
type
==
REDIS_REPLY_MAP
||
parent
->
type
==
REDIS_REPLY_SET
);
parent
->
element
[
task
->
idx
]
=
r
;
}
return
r
;
}
static
void
*
createDoubleObject
(
const
redisReadTask
*
task
,
double
value
,
char
*
str
,
size_t
len
)
{
redisReply
*
r
,
*
parent
;
r
=
createReplyObject
(
REDIS_REPLY_DOUBLE
);
if
(
r
==
NULL
)
return
NULL
;
r
->
dval
=
value
;
r
->
str
=
malloc
(
len
+
1
);
if
(
r
->
str
==
NULL
)
{
freeReplyObject
(
r
);
return
NULL
;
}
/* The double reply also has the original protocol string representing a
* double as a null terminated string. This way the caller does not need
* to format back for string conversion, especially since Redis does efforts
* to make the string more human readable avoiding the calssical double
* decimal string conversion artifacts. */
memcpy
(
r
->
str
,
str
,
len
);
r
->
str
[
len
]
=
'\0'
;
if
(
task
->
parent
)
{
parent
=
task
->
parent
->
obj
;
assert
(
parent
->
type
==
REDIS_REPLY_ARRAY
||
parent
->
type
==
REDIS_REPLY_MAP
||
parent
->
type
==
REDIS_REPLY_SET
);
parent
->
element
[
task
->
idx
]
=
r
;
}
return
r
;
}
static
void
*
createNilObject
(
const
redisReadTask
*
task
)
{
redisReply
*
r
,
*
parent
;
r
=
createReplyObject
(
REDIS_REPLY_NIL
);
if
(
r
==
NULL
)
return
NULL
;
if
(
task
->
parent
)
{
parent
=
task
->
parent
->
obj
;
assert
(
parent
->
type
==
REDIS_REPLY_ARRAY
||
parent
->
type
==
REDIS_REPLY_MAP
||
parent
->
type
==
REDIS_REPLY_SET
);
parent
->
element
[
task
->
idx
]
=
r
;
}
return
r
;
}
static
void
*
createBoolObject
(
const
redisReadTask
*
task
,
int
bval
)
{
redisReply
*
r
,
*
parent
;
r
=
createReplyObject
(
REDIS_REPLY_BOOL
);
if
(
r
==
NULL
)
return
NULL
;
r
->
integer
=
bval
!=
0
;
if
(
task
->
parent
)
{
parent
=
task
->
parent
->
obj
;
assert
(
parent
->
type
==
REDIS_REPLY_ARRAY
||
parent
->
type
==
REDIS_REPLY_MAP
||
parent
->
type
==
REDIS_REPLY_SET
);
parent
->
element
[
task
->
idx
]
=
r
;
}
return
r
;
}
/* Return the number of digits of 'v' when converted to string in radix 10.
* Implementation borrowed from link in redis/src/util.c:string2ll(). */
static
uint32_t
countDigits
(
uint64_t
v
)
{
uint32_t
result
=
1
;
for
(;;)
{
if
(
v
<
10
)
return
result
;
if
(
v
<
100
)
return
result
+
1
;
if
(
v
<
1000
)
return
result
+
2
;
if
(
v
<
10000
)
return
result
+
3
;
v
/=
10000U
;
result
+=
4
;
}
}
/* Helper that calculates the bulk length given a certain string length. */
static
size_t
bulklen
(
size_t
len
)
{
return
1
+
countDigits
(
len
)
+
2
+
len
+
2
;
}
int
redisvFormatCommand
(
char
**
target
,
const
char
*
format
,
va_list
ap
)
{
const
char
*
c
=
format
;
char
*
cmd
=
NULL
;
/* final command */
int
pos
;
/* position in final command */
sds
curarg
,
newarg
;
/* current argument */
int
touched
=
0
;
/* was the current argument touched? */
char
**
curargv
=
NULL
,
**
newargv
=
NULL
;
int
argc
=
0
;
int
totlen
=
0
;
int
error_type
=
0
;
/* 0 = no error; -1 = memory error; -2 = format error */
int
j
;
/* Abort if there is not target to set */
if
(
target
==
NULL
)
return
-
1
;
/* Build the command string accordingly to protocol */
curarg
=
sdsempty
();
if
(
curarg
==
NULL
)
return
-
1
;
while
(
*
c
!=
'\0'
)
{
if
(
*
c
!=
'%'
||
c
[
1
]
==
'\0'
)
{
if
(
*
c
==
' '
)
{
if
(
touched
)
{
newargv
=
realloc
(
curargv
,
sizeof
(
char
*
)
*
(
argc
+
1
));
if
(
newargv
==
NULL
)
goto
memory_err
;
curargv
=
newargv
;
curargv
[
argc
++
]
=
curarg
;
totlen
+=
bulklen
(
sdslen
(
curarg
));
/* curarg is put in argv so it can be overwritten. */
curarg
=
sdsempty
();
if
(
curarg
==
NULL
)
goto
memory_err
;
touched
=
0
;
}
}
else
{
newarg
=
sdscatlen
(
curarg
,
c
,
1
);
if
(
newarg
==
NULL
)
goto
memory_err
;
curarg
=
newarg
;
touched
=
1
;
}
}
else
{
char
*
arg
;
size_t
size
;
/* Set newarg so it can be checked even if it is not touched. */
newarg
=
curarg
;
switch
(
c
[
1
])
{
case
's'
:
arg
=
va_arg
(
ap
,
char
*
);
size
=
strlen
(
arg
);
if
(
size
>
0
)
newarg
=
sdscatlen
(
curarg
,
arg
,
size
);
break
;
case
'b'
:
arg
=
va_arg
(
ap
,
char
*
);
size
=
va_arg
(
ap
,
size_t
);
if
(
size
>
0
)
newarg
=
sdscatlen
(
curarg
,
arg
,
size
);
break
;
case
'%'
:
newarg
=
sdscat
(
curarg
,
"%"
);
break
;
default:
/* Try to detect printf format */
{
static
const
char
intfmts
[]
=
"diouxX"
;
static
const
char
flags
[]
=
"#0-+ "
;
char
_format
[
16
];
const
char
*
_p
=
c
+
1
;
size_t
_l
=
0
;
va_list
_cpy
;
/* Flags */
while
(
*
_p
!=
'\0'
&&
strchr
(
flags
,
*
_p
)
!=
NULL
)
_p
++
;
/* Field width */
while
(
*
_p
!=
'\0'
&&
isdigit
(
*
_p
))
_p
++
;
/* Precision */
if
(
*
_p
==
'.'
)
{
_p
++
;
while
(
*
_p
!=
'\0'
&&
isdigit
(
*
_p
))
_p
++
;
}
/* Copy va_list before consuming with va_arg */
va_copy
(
_cpy
,
ap
);
/* Integer conversion (without modifiers) */
if
(
strchr
(
intfmts
,
*
_p
)
!=
NULL
)
{
va_arg
(
ap
,
int
);
goto
fmt_valid
;
}
/* Double conversion (without modifiers) */
if
(
strchr
(
"eEfFgGaA"
,
*
_p
)
!=
NULL
)
{
va_arg
(
ap
,
double
);
goto
fmt_valid
;
}
/* Size: char */
if
(
_p
[
0
]
==
'h'
&&
_p
[
1
]
==
'h'
)
{
_p
+=
2
;
if
(
*
_p
!=
'\0'
&&
strchr
(
intfmts
,
*
_p
)
!=
NULL
)
{
va_arg
(
ap
,
int
);
/* char gets promoted to int */
goto
fmt_valid
;
}
goto
fmt_invalid
;
}
/* Size: short */
if
(
_p
[
0
]
==
'h'
)
{
_p
+=
1
;
if
(
*
_p
!=
'\0'
&&
strchr
(
intfmts
,
*
_p
)
!=
NULL
)
{
va_arg
(
ap
,
int
);
/* short gets promoted to int */
goto
fmt_valid
;
}
goto
fmt_invalid
;
}
/* Size: long long */
if
(
_p
[
0
]
==
'l'
&&
_p
[
1
]
==
'l'
)
{
_p
+=
2
;
if
(
*
_p
!=
'\0'
&&
strchr
(
intfmts
,
*
_p
)
!=
NULL
)
{
va_arg
(
ap
,
long
long
);
goto
fmt_valid
;
}
goto
fmt_invalid
;
}
/* Size: long */
if
(
_p
[
0
]
==
'l'
)
{
_p
+=
1
;
if
(
*
_p
!=
'\0'
&&
strchr
(
intfmts
,
*
_p
)
!=
NULL
)
{
va_arg
(
ap
,
long
);
goto
fmt_valid
;
}
goto
fmt_invalid
;
}
fmt_invalid:
va_end
(
_cpy
);
goto
format_err
;
fmt_valid:
_l
=
(
_p
+
1
)
-
c
;
if
(
_l
<
sizeof
(
_format
)
-
2
)
{
memcpy
(
_format
,
c
,
_l
);
_format
[
_l
]
=
'\0'
;
newarg
=
sdscatvprintf
(
curarg
,
_format
,
_cpy
);
/* Update current position (note: outer blocks
* increment c twice so compensate here) */
c
=
_p
-
1
;
}
va_end
(
_cpy
);
break
;
}
}
if
(
newarg
==
NULL
)
goto
memory_err
;
curarg
=
newarg
;
touched
=
1
;
c
++
;
}
c
++
;
}
/* Add the last argument if needed */
if
(
touched
)
{
newargv
=
realloc
(
curargv
,
sizeof
(
char
*
)
*
(
argc
+
1
));
if
(
newargv
==
NULL
)
goto
memory_err
;
curargv
=
newargv
;
curargv
[
argc
++
]
=
curarg
;
totlen
+=
bulklen
(
sdslen
(
curarg
));
}
else
{
sdsfree
(
curarg
);
}
/* Clear curarg because it was put in curargv or was free'd. */
curarg
=
NULL
;
/* Add bytes needed to hold multi bulk count */
totlen
+=
1
+
countDigits
(
argc
)
+
2
;
/* Build the command at protocol level */
cmd
=
malloc
(
totlen
+
1
);
if
(
cmd
==
NULL
)
goto
memory_err
;
pos
=
sprintf
(
cmd
,
"*%d
\r\n
"
,
argc
);
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
pos
+=
sprintf
(
cmd
+
pos
,
"$%zu
\r\n
"
,
sdslen
(
curargv
[
j
]));
memcpy
(
cmd
+
pos
,
curargv
[
j
],
sdslen
(
curargv
[
j
]));
pos
+=
sdslen
(
curargv
[
j
]);
sdsfree
(
curargv
[
j
]);
cmd
[
pos
++
]
=
'\r'
;
cmd
[
pos
++
]
=
'\n'
;
}
assert
(
pos
==
totlen
);
cmd
[
pos
]
=
'\0'
;
free
(
curargv
);
*
target
=
cmd
;
return
totlen
;
format_err:
error_type
=
-
2
;
goto
cleanup
;
memory_err:
error_type
=
-
1
;
goto
cleanup
;
cleanup:
if
(
curargv
)
{
while
(
argc
--
)
sdsfree
(
curargv
[
argc
]);
free
(
curargv
);
}
sdsfree
(
curarg
);
free
(
cmd
);
return
error_type
;
}
/* Format a command according to the Redis protocol. This function
* takes a format similar to printf:
*
* %s represents a C null terminated string you want to interpolate
* %b represents a binary safe string
*
* When using %b you need to provide both the pointer to the string
* and the length in bytes as a size_t. Examples:
*
* len = redisFormatCommand(target, "GET %s", mykey);
* len = redisFormatCommand(target, "SET %s %b", mykey, myval, myvallen);
*/
int
redisFormatCommand
(
char
**
target
,
const
char
*
format
,
...)
{
va_list
ap
;
int
len
;
va_start
(
ap
,
format
);
len
=
redisvFormatCommand
(
target
,
format
,
ap
);
va_end
(
ap
);
/* The API says "-1" means bad result, but we now also return "-2" in some
* cases. Force the return value to always be -1. */
if
(
len
<
0
)
len
=
-
1
;
return
len
;
}
/* Format a command according to the Redis protocol using an sds string and
* sdscatfmt for the processing of arguments. This function takes the
* number of arguments, an array with arguments and an array with their
* lengths. If the latter is set to NULL, strlen will be used to compute the
* argument lengths.
*/
int
redisFormatSdsCommandArgv
(
sds
*
target
,
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
)
{
sds
cmd
;
unsigned
long
long
totlen
;
int
j
;
size_t
len
;
/* Abort on a NULL target */
if
(
target
==
NULL
)
return
-
1
;
/* Calculate our total size */
totlen
=
1
+
countDigits
(
argc
)
+
2
;
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
len
=
argvlen
?
argvlen
[
j
]
:
strlen
(
argv
[
j
]);
totlen
+=
bulklen
(
len
);
}
/* Use an SDS string for command construction */
cmd
=
sdsempty
();
if
(
cmd
==
NULL
)
return
-
1
;
/* We already know how much storage we need */
cmd
=
sdsMakeRoomFor
(
cmd
,
totlen
);
if
(
cmd
==
NULL
)
return
-
1
;
/* Construct command */
cmd
=
sdscatfmt
(
cmd
,
"*%i
\r\n
"
,
argc
);
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
len
=
argvlen
?
argvlen
[
j
]
:
strlen
(
argv
[
j
]);
cmd
=
sdscatfmt
(
cmd
,
"$%u
\r\n
"
,
len
);
cmd
=
sdscatlen
(
cmd
,
argv
[
j
],
len
);
cmd
=
sdscatlen
(
cmd
,
"
\r\n
"
,
sizeof
(
"
\r\n
"
)
-
1
);
}
assert
(
sdslen
(
cmd
)
==
totlen
);
*
target
=
cmd
;
return
totlen
;
}
void
redisFreeSdsCommand
(
sds
cmd
)
{
sdsfree
(
cmd
);
}
/* Format a command according to the Redis protocol. This function takes the
* number of arguments, an array with arguments and an array with their
* lengths. If the latter is set to NULL, strlen will be used to compute the
* argument lengths.
*/
int
redisFormatCommandArgv
(
char
**
target
,
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
)
{
char
*
cmd
=
NULL
;
/* final command */
int
pos
;
/* position in final command */
size_t
len
;
int
totlen
,
j
;
/* Abort on a NULL target */
if
(
target
==
NULL
)
return
-
1
;
/* Calculate number of bytes needed for the command */
totlen
=
1
+
countDigits
(
argc
)
+
2
;
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
len
=
argvlen
?
argvlen
[
j
]
:
strlen
(
argv
[
j
]);
totlen
+=
bulklen
(
len
);
}
/* Build the command at protocol level */
cmd
=
malloc
(
totlen
+
1
);
if
(
cmd
==
NULL
)
return
-
1
;
pos
=
sprintf
(
cmd
,
"*%d
\r\n
"
,
argc
);
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
len
=
argvlen
?
argvlen
[
j
]
:
strlen
(
argv
[
j
]);
pos
+=
sprintf
(
cmd
+
pos
,
"$%zu
\r\n
"
,
len
);
memcpy
(
cmd
+
pos
,
argv
[
j
],
len
);
pos
+=
len
;
cmd
[
pos
++
]
=
'\r'
;
cmd
[
pos
++
]
=
'\n'
;
}
assert
(
pos
==
totlen
);
cmd
[
pos
]
=
'\0'
;
*
target
=
cmd
;
return
totlen
;
}
void
redisFreeCommand
(
char
*
cmd
)
{
free
(
cmd
);
}
void
__redisSetError
(
redisContext
*
c
,
int
type
,
const
char
*
str
)
{
size_t
len
;
c
->
err
=
type
;
if
(
str
!=
NULL
)
{
len
=
strlen
(
str
);
len
=
len
<
(
sizeof
(
c
->
errstr
)
-
1
)
?
len
:
(
sizeof
(
c
->
errstr
)
-
1
);
memcpy
(
c
->
errstr
,
str
,
len
);
c
->
errstr
[
len
]
=
'\0'
;
}
else
{
/* Only REDIS_ERR_IO may lack a description! */
assert
(
type
==
REDIS_ERR_IO
);
strerror_r
(
errno
,
c
->
errstr
,
sizeof
(
c
->
errstr
));
}
}
redisReader
*
redisReaderCreate
(
void
)
{
return
redisReaderCreateWithFunctions
(
&
defaultFunctions
);
}
static
redisContext
*
redisContextInit
(
const
redisOptions
*
options
)
{
redisContext
*
c
;
c
=
calloc
(
1
,
sizeof
(
*
c
));
if
(
c
==
NULL
)
return
NULL
;
c
->
funcs
=
&
redisContextDefaultFuncs
;
c
->
obuf
=
sdsempty
();
c
->
reader
=
redisReaderCreate
();
c
->
fd
=
REDIS_INVALID_FD
;
if
(
c
->
obuf
==
NULL
||
c
->
reader
==
NULL
)
{
redisFree
(
c
);
return
NULL
;
}
(
void
)
options
;
/* options are used in other functions */
return
c
;
}
void
redisFree
(
redisContext
*
c
)
{
if
(
c
==
NULL
)
return
;
redisNetClose
(
c
);
sdsfree
(
c
->
obuf
);
redisReaderFree
(
c
->
reader
);
free
(
c
->
tcp
.
host
);
free
(
c
->
tcp
.
source_addr
);
free
(
c
->
unix_sock
.
path
);
free
(
c
->
timeout
);
free
(
c
->
saddr
);
if
(
c
->
funcs
->
free_privdata
)
{
c
->
funcs
->
free_privdata
(
c
->
privdata
);
}
memset
(
c
,
0xff
,
sizeof
(
*
c
));
free
(
c
);
}
redisFD
redisFreeKeepFd
(
redisContext
*
c
)
{
redisFD
fd
=
c
->
fd
;
c
->
fd
=
REDIS_INVALID_FD
;
redisFree
(
c
);
return
fd
;
}
int
redisReconnect
(
redisContext
*
c
)
{
c
->
err
=
0
;
memset
(
c
->
errstr
,
'\0'
,
strlen
(
c
->
errstr
));
if
(
c
->
privdata
&&
c
->
funcs
->
free_privdata
)
{
c
->
funcs
->
free_privdata
(
c
->
privdata
);
c
->
privdata
=
NULL
;
}
redisNetClose
(
c
);
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
;
}
redisContext
*
redisConnectWithOptions
(
const
redisOptions
*
options
)
{
redisContext
*
c
=
redisContextInit
(
options
);
if
(
c
==
NULL
)
{
return
NULL
;
}
if
(
!
(
options
->
options
&
REDIS_OPT_NONBLOCK
))
{
c
->
flags
|=
REDIS_BLOCK
;
}
if
(
options
->
options
&
REDIS_OPT_REUSEADDR
)
{
c
->
flags
|=
REDIS_REUSEADDR
;
}
if
(
options
->
options
&
REDIS_OPT_NOAUTOFREE
)
{
c
->
flags
|=
REDIS_NO_AUTO_FREE
;
}
if
(
options
->
type
==
REDIS_CONN_TCP
)
{
redisContextConnectBindTcp
(
c
,
options
->
endpoint
.
tcp
.
ip
,
options
->
endpoint
.
tcp
.
port
,
options
->
timeout
,
options
->
endpoint
.
tcp
.
source_addr
);
}
else
if
(
options
->
type
==
REDIS_CONN_UNIX
)
{
redisContextConnectUnix
(
c
,
options
->
endpoint
.
unix_socket
,
options
->
timeout
);
}
else
if
(
options
->
type
==
REDIS_CONN_USERFD
)
{
c
->
fd
=
options
->
endpoint
.
fd
;
c
->
flags
|=
REDIS_CONNECTED
;
}
else
{
// Unknown type - FIXME - FREE
return
NULL
;
}
if
(
options
->
timeout
!=
NULL
&&
(
c
->
flags
&
REDIS_BLOCK
)
&&
c
->
fd
!=
REDIS_INVALID_FD
)
{
redisContextSetTimeout
(
c
,
*
options
->
timeout
);
}
return
c
;
}
/* 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. */
redisContext
*
redisConnect
(
const
char
*
ip
,
int
port
)
{
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectWithTimeout
(
const
char
*
ip
,
int
port
,
const
struct
timeval
tv
)
{
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
options
.
timeout
=
&
tv
;
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectNonBlock
(
const
char
*
ip
,
int
port
)
{
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
options
.
options
|=
REDIS_OPT_NONBLOCK
;
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectBindNonBlock
(
const
char
*
ip
,
int
port
,
const
char
*
source_addr
)
{
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
options
.
endpoint
.
tcp
.
source_addr
=
source_addr
;
options
.
options
|=
REDIS_OPT_NONBLOCK
;
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectBindNonBlockWithReuse
(
const
char
*
ip
,
int
port
,
const
char
*
source_addr
)
{
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_TCP
(
&
options
,
ip
,
port
);
options
.
endpoint
.
tcp
.
source_addr
=
source_addr
;
options
.
options
|=
REDIS_OPT_NONBLOCK
|
REDIS_OPT_REUSEADDR
;
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectUnix
(
const
char
*
path
)
{
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_UNIX
(
&
options
,
path
);
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectUnixWithTimeout
(
const
char
*
path
,
const
struct
timeval
tv
)
{
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_UNIX
(
&
options
,
path
);
options
.
timeout
=
&
tv
;
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectUnixNonBlock
(
const
char
*
path
)
{
redisOptions
options
=
{
0
};
REDIS_OPTIONS_SET_UNIX
(
&
options
,
path
);
options
.
options
|=
REDIS_OPT_NONBLOCK
;
return
redisConnectWithOptions
(
&
options
);
}
redisContext
*
redisConnectFd
(
redisFD
fd
)
{
redisOptions
options
=
{
0
};
options
.
type
=
REDIS_CONN_USERFD
;
options
.
endpoint
.
fd
=
fd
;
return
redisConnectWithOptions
(
&
options
);
}
/* Set read/write timeout on a blocking socket. */
int
redisSetTimeout
(
redisContext
*
c
,
const
struct
timeval
tv
)
{
if
(
c
->
flags
&
REDIS_BLOCK
)
return
redisContextSetTimeout
(
c
,
tv
);
return
REDIS_ERR
;
}
/* Enable connection KeepAlive. */
int
redisEnableKeepAlive
(
redisContext
*
c
)
{
if
(
redisKeepAlive
(
c
,
REDIS_KEEPALIVE_INTERVAL
)
!=
REDIS_OK
)
return
REDIS_ERR
;
return
REDIS_OK
;
}
/* Use this function to handle a read event on the descriptor. It will try
* and read some bytes from the socket and feed them to the reply parser.
*
* After this function is called, you may use redisGetReplyFromReader to
* see if there is a reply available. */
int
redisBufferRead
(
redisContext
*
c
)
{
char
buf
[
1024
*
16
];
int
nread
;
/* Return early when the context has seen an error. */
if
(
c
->
err
)
return
REDIS_ERR
;
nread
=
c
->
funcs
->
read
(
c
,
buf
,
sizeof
(
buf
));
if
(
nread
>
0
)
{
if
(
redisReaderFeed
(
c
->
reader
,
buf
,
nread
)
!=
REDIS_OK
)
{
__redisSetError
(
c
,
c
->
reader
->
err
,
c
->
reader
->
errstr
);
return
REDIS_ERR
;
}
else
{
}
}
else
if
(
nread
<
0
)
{
return
REDIS_ERR
;
}
return
REDIS_OK
;
}
/* Write the output buffer to the socket.
*
* Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was
* successfully written to the socket. When the buffer is empty after the
* write operation, "done" is set to 1 (if given).
*
* Returns REDIS_ERR if an error occurred trying to write and sets
* c->errstr to hold the appropriate error string.
*/
int
redisBufferWrite
(
redisContext
*
c
,
int
*
done
)
{
/* Return early when the context has seen an error. */
if
(
c
->
err
)
return
REDIS_ERR
;
if
(
sdslen
(
c
->
obuf
)
>
0
)
{
int
nwritten
=
c
->
funcs
->
write
(
c
);
if
(
nwritten
<
0
)
{
return
REDIS_ERR
;
}
else
if
(
nwritten
>
0
)
{
if
(
nwritten
==
(
signed
)
sdslen
(
c
->
obuf
))
{
sdsfree
(
c
->
obuf
);
c
->
obuf
=
sdsempty
();
}
else
{
sdsrange
(
c
->
obuf
,
nwritten
,
-
1
);
}
}
}
if
(
done
!=
NULL
)
*
done
=
(
sdslen
(
c
->
obuf
)
==
0
);
return
REDIS_OK
;
}
/* Internal helper function to try and get a reply from the reader,
* or set an error in the context otherwise. */
int
redisGetReplyFromReader
(
redisContext
*
c
,
void
**
reply
)
{
if
(
redisReaderGetReply
(
c
->
reader
,
reply
)
==
REDIS_ERR
)
{
__redisSetError
(
c
,
c
->
reader
->
err
,
c
->
reader
->
errstr
);
return
REDIS_ERR
;
}
return
REDIS_OK
;
}
int
redisGetReply
(
redisContext
*
c
,
void
**
reply
)
{
int
wdone
=
0
;
void
*
aux
=
NULL
;
/* Try to read pending replies */
if
(
redisGetReplyFromReader
(
c
,
&
aux
)
==
REDIS_ERR
)
return
REDIS_ERR
;
/* For the blocking context, flush output buffer and read reply */
if
(
aux
==
NULL
&&
c
->
flags
&
REDIS_BLOCK
)
{
/* Write until done */
do
{
if
(
redisBufferWrite
(
c
,
&
wdone
)
==
REDIS_ERR
)
return
REDIS_ERR
;
}
while
(
!
wdone
);
/* Read until there is a reply */
do
{
if
(
redisBufferRead
(
c
)
==
REDIS_ERR
)
return
REDIS_ERR
;
if
(
redisGetReplyFromReader
(
c
,
&
aux
)
==
REDIS_ERR
)
return
REDIS_ERR
;
}
while
(
aux
==
NULL
);
}
/* Set reply object */
if
(
reply
!=
NULL
)
*
reply
=
aux
;
return
REDIS_OK
;
}
/* Helper function for the redisAppendCommand* family of functions.
*
* Write a formatted command to the output buffer. When this family
* is used, you need to call redisGetReply yourself to retrieve
* the reply (or replies in pub/sub).
*/
int
__redisAppendCommand
(
redisContext
*
c
,
const
char
*
cmd
,
size_t
len
)
{
sds
newbuf
;
newbuf
=
sdscatlen
(
c
->
obuf
,
cmd
,
len
);
if
(
newbuf
==
NULL
)
{
__redisSetError
(
c
,
REDIS_ERR_OOM
,
"Out of memory"
);
return
REDIS_ERR
;
}
c
->
obuf
=
newbuf
;
return
REDIS_OK
;
}
int
redisAppendFormattedCommand
(
redisContext
*
c
,
const
char
*
cmd
,
size_t
len
)
{
if
(
__redisAppendCommand
(
c
,
cmd
,
len
)
!=
REDIS_OK
)
{
return
REDIS_ERR
;
}
return
REDIS_OK
;
}
int
redisvAppendCommand
(
redisContext
*
c
,
const
char
*
format
,
va_list
ap
)
{
char
*
cmd
;
int
len
;
len
=
redisvFormatCommand
(
&
cmd
,
format
,
ap
);
if
(
len
==
-
1
)
{
__redisSetError
(
c
,
REDIS_ERR_OOM
,
"Out of memory"
);
return
REDIS_ERR
;
}
else
if
(
len
==
-
2
)
{
__redisSetError
(
c
,
REDIS_ERR_OTHER
,
"Invalid format string"
);
return
REDIS_ERR
;
}
if
(
__redisAppendCommand
(
c
,
cmd
,
len
)
!=
REDIS_OK
)
{
free
(
cmd
);
return
REDIS_ERR
;
}
free
(
cmd
);
return
REDIS_OK
;
}
int
redisAppendCommand
(
redisContext
*
c
,
const
char
*
format
,
...)
{
va_list
ap
;
int
ret
;
va_start
(
ap
,
format
);
ret
=
redisvAppendCommand
(
c
,
format
,
ap
);
va_end
(
ap
);
return
ret
;
}
int
redisAppendCommandArgv
(
redisContext
*
c
,
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
)
{
sds
cmd
;
int
len
;
len
=
redisFormatSdsCommandArgv
(
&
cmd
,
argc
,
argv
,
argvlen
);
if
(
len
==
-
1
)
{
__redisSetError
(
c
,
REDIS_ERR_OOM
,
"Out of memory"
);
return
REDIS_ERR
;
}
if
(
__redisAppendCommand
(
c
,
cmd
,
len
)
!=
REDIS_OK
)
{
sdsfree
(
cmd
);
return
REDIS_ERR
;
}
sdsfree
(
cmd
);
return
REDIS_OK
;
}
/* Helper function for the redisCommand* family of functions.
*
* Write a formatted command to the output buffer. If the given context is
* blocking, immediately read the reply into the "reply" pointer. When the
* context is non-blocking, the "reply" pointer will not be used and the
* command is simply appended to the write buffer.
*
* Returns the reply when a reply was successfully retrieved. Returns NULL
* otherwise. When NULL is returned in a blocking context, the error field
* in the context will be set.
*/
static
void
*
__redisBlockForReply
(
redisContext
*
c
)
{
void
*
reply
;
if
(
c
->
flags
&
REDIS_BLOCK
)
{
if
(
redisGetReply
(
c
,
&
reply
)
!=
REDIS_OK
)
return
NULL
;
return
reply
;
}
return
NULL
;
}
void
*
redisvCommand
(
redisContext
*
c
,
const
char
*
format
,
va_list
ap
)
{
if
(
redisvAppendCommand
(
c
,
format
,
ap
)
!=
REDIS_OK
)
return
NULL
;
return
__redisBlockForReply
(
c
);
}
void
*
redisCommand
(
redisContext
*
c
,
const
char
*
format
,
...)
{
va_list
ap
;
va_start
(
ap
,
format
);
void
*
reply
=
redisvCommand
(
c
,
format
,
ap
);
va_end
(
ap
);
return
reply
;
}
void
*
redisCommandArgv
(
redisContext
*
c
,
int
argc
,
const
char
**
argv
,
const
size_t
*
argvlen
)
{
if
(
redisAppendCommandArgv
(
c
,
argc
,
argv
,
argvlen
)
!=
REDIS_OK
)
return
NULL
;
return
__redisBlockForReply
(
c
);
}
deps/hiredis/hiredis.h
deleted
100644 → 0
View file @
c17e597d
/*
* 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 */
#ifndef _MSC_VER
#include <sys/time.h>
/* for struct timeval */
#else
struct
timeval
;
/* forward declaration */
#endif
#include <stdint.h>
/* uintXX_t, etc */
#include "sds.h"
/* for sds */
#define HIREDIS_MAJOR 0
#define HIREDIS_MINOR 14
#define HIREDIS_PATCH 0
#define HIREDIS_SONAME 0.14
/* 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
/**
* Flag that indicates the user does not want the context to
* be automatically freed upon error
*/
#define REDIS_NO_AUTO_FREE 0x200
#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
#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 */
double
dval
;
/* The double when type is REDIS_REPLY_DOUBLE */
size_t
len
;
/* Length of string */
char
*
str
;
/* Used for REDIS_REPLY_ERROR, REDIS_REPLY_STRING
and REDIS_REPLY_DOUBLE (in additionl to dval). */
char
vtype
[
4
];
/* Used for REDIS_REPLY_VERB, contains the null
terminated 3 character content type, such as "txt". */
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
,
REDIS_CONN_USERFD
};
struct
redisSsl
;
#define REDIS_OPT_NONBLOCK 0x01
#define REDIS_OPT_REUSEADDR 0x02
/**
* Don't automatically free the async object on a connection failure,
* or other implicit conditions. Only free on an explicit call to disconnect() or free()
*/
#define REDIS_OPT_NOAUTOFREE 0x04
/* In Unix systems a file descriptor is a regular signed int, with -1
* representing an invalid descriptor. In Windows it is a SOCKET
* (32- or 64-bit unsigned integer depending on the architecture), where
* all bits set (~0) is INVALID_SOCKET. */
#ifndef _WIN32
typedef
int
redisFD
;
#define REDIS_INVALID_FD -1
#else
#ifdef _WIN64
typedef
unsigned
long
long
redisFD
;
/* SOCKET = 64-bit UINT_PTR */
#else
typedef
unsigned
long
redisFD
;
/* SOCKET = 32-bit UINT_PTR */
#endif
#define REDIS_INVALID_FD ((redisFD)(~0))
/* INVALID_SOCKET */
#endif
typedef
struct
{
/*
* the type of connection to use. This also indicates which
* `endpoint` member field to use
*/
int
type
;
/* bit field of REDIS_OPT_xxx */
int
options
;
/* timeout value. if NULL, no timeout is used */
const
struct
timeval
*
timeout
;
union
{
/** use this field for tcp/ip connections */
struct
{
const
char
*
source_addr
;
const
char
*
ip
;
int
port
;
}
tcp
;
/** use this field for unix domain sockets */
const
char
*
unix_socket
;
/**
* use this field to have hiredis operate an already-open
* file descriptor */
redisFD
fd
;
}
endpoint
;
}
redisOptions
;
/**
* Helper macros to initialize options to their specified fields.
*/
#define REDIS_OPTIONS_SET_TCP(opts, ip_, port_) \
(opts)->type = REDIS_CONN_TCP; \
(opts)->endpoint.tcp.ip = ip_; \
(opts)->endpoint.tcp.port = port_;
#define REDIS_OPTIONS_SET_UNIX(opts, path) \
(opts)->type = REDIS_CONN_UNIX; \
(opts)->endpoint.unix_socket = path;
struct
redisAsyncContext
;
struct
redisContext
;
typedef
struct
redisContextFuncs
{
void
(
*
free_privdata
)(
void
*
);
void
(
*
async_read
)(
struct
redisAsyncContext
*
);
void
(
*
async_write
)(
struct
redisAsyncContext
*
);
int
(
*
read
)(
struct
redisContext
*
,
char
*
,
size_t
);
int
(
*
write
)(
struct
redisContext
*
);
}
redisContextFuncs
;
/* Context for a connection to Redis */
typedef
struct
redisContext
{
const
redisContextFuncs
*
funcs
;
/* Function table */
int
err
;
/* Error flags, 0 when there is no error */
char
errstr
[
128
];
/* String representation of error when applicable */
redisFD
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
;
/* For non-blocking connect */
struct
sockadr
*
saddr
;
size_t
addrlen
;
/* Additional private data for hiredis addons such as SSL */
void
*
privdata
;
}
redisContext
;
redisContext
*
redisConnectWithOptions
(
const
redisOptions
*
options
);
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
(
redisFD
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
);
redisFD
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
deps/hiredis/hiredis.pc.in
deleted
100644 → 0
View file @
c17e597d
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
pkgincludedir=${includedir}/hiredis
Name: hiredis
Description: Minimalistic C client library for Redis.
Version: @PROJECT_VERSION@
Libs: -L${libdir} -lhiredis
Cflags: -I${pkgincludedir} -D_FILE_OFFSET_BITS=64
deps/hiredis/hiredis_ssl.h
deleted
100644 → 0
View file @
c17e597d
/*
* Copyright (c) 2019, Redis Labs
*
* 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_SSL_H
#define __HIREDIS_SSL_H
/* This is the underlying struct for SSL in ssl.h, which is not included to
* keep build dependencies short here.
*/
struct
ssl_st
;
/**
* Secure the connection using SSL. This should be done before any command is
* executed on the connection.
*/
int
redisSecureConnection
(
redisContext
*
c
,
const
char
*
capath
,
const
char
*
certpath
,
const
char
*
keypath
,
const
char
*
servername
);
/**
* Initiate SSL/TLS negotiation on a provided context.
*/
int
redisInitiateSSL
(
redisContext
*
c
,
struct
ssl_st
*
ssl
);
#endif
/* __HIREDIS_SSL_H */
deps/hiredis/hiredis_ssl.pc.in
deleted
100644 → 0
View file @
c17e597d
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
pkgincludedir=${includedir}/hiredis
Name: hiredis_ssl
Description: SSL Support for hiredis.
Version: @PROJECT_VERSION@
Requires: hiredis
Libs: -L${libdir} -lhiredis_ssl
Libs.private: -lssl -lcrypto
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment