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
7fc4ce13
Commit
7fc4ce13
authored
Nov 03, 2010
by
Pieter Noordhuis
Browse files
Use hiredis from redis-cli
parent
24f753a8
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/Makefile
View file @
7fc4ce13
...
@@ -114,7 +114,11 @@ redis-benchmark: $(BENCHOBJ)
...
@@ -114,7 +114,11 @@ redis-benchmark: $(BENCHOBJ)
$(CC)
-o
$(BENCHPRGNAME)
$(CCOPT)
$(DEBUG)
$(BENCHOBJ)
$(CC)
-o
$(BENCHPRGNAME)
$(CCOPT)
$(DEBUG)
$(BENCHOBJ)
redis-cli
:
$(CLIOBJ)
redis-cli
:
$(CLIOBJ)
$(CC)
-o
$(CLIPRGNAME)
$(CCOPT)
$(DEBUG)
$(CLIOBJ)
cd
../deps/hiredis
&&
make static
$(CC)
-o
$(CLIPRGNAME)
$(CCOPT)
$(DEBUG)
$(CLIOBJ)
../deps/hiredis/libhiredis.a
redis-cli.o
:
$(CC)
-c
$(CFLAGS)
-I
../deps/hiredis
$(DEBUG)
$(COMPILE_TIME)
$<
redis-check-dump
:
$(CHECKDUMPOBJ)
redis-check-dump
:
$(CHECKDUMPOBJ)
$(CC)
-o
$(CHECKDUMPPRGNAME)
$(CCOPT)
$(DEBUG)
$(CHECKDUMPOBJ)
$(CC)
-o
$(CHECKDUMPPRGNAME)
$(CCOPT)
$(DEBUG)
$(CHECKDUMPOBJ)
...
...
src/redis-cli.c
View file @
7fc4ce13
...
@@ -40,14 +40,14 @@
...
@@ -40,14 +40,14 @@
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/time.h>
#include "
anet
.h"
#include "
hiredis
.h"
#include "sds.h"
#include "sds.h"
#include "adlist.h"
#include "zmalloc.h"
#include "zmalloc.h"
#include "linenoise.h"
#include "linenoise.h"
#define REDIS_NOTUSED(V) ((void) V)
#define REDIS_NOTUSED(V) ((void) V)
static
redisContext
*
context
;
static
struct
config
{
static
struct
config
{
char
*
hostip
;
char
*
hostip
;
int
hostport
;
int
hostport
;
...
@@ -66,7 +66,6 @@ static struct config {
...
@@ -66,7 +66,6 @@ static struct config {
char
*
historyfile
;
char
*
historyfile
;
}
config
;
}
config
;
static
int
cliReadReply
(
int
fd
);
static
void
usage
();
static
void
usage
();
/*------------------------------------------------------------------------------
/*------------------------------------------------------------------------------
...
@@ -83,197 +82,156 @@ static long long mstime(void) {
...
@@ -83,197 +82,156 @@ static long long mstime(void) {
return
mst
;
return
mst
;
}
}
static
void
printStringRepr
(
char
*
s
,
int
len
)
{
printf
(
"
\"
"
);
while
(
len
--
)
{
switch
(
*
s
)
{
case
'\\'
:
case
'"'
:
printf
(
"
\\
%c"
,
*
s
);
break
;
case
'\n'
:
printf
(
"
\\
n"
);
break
;
case
'\r'
:
printf
(
"
\\
r"
);
break
;
case
'\t'
:
printf
(
"
\\
t"
);
break
;
case
'\a'
:
printf
(
"
\\
a"
);
break
;
case
'\b'
:
printf
(
"
\\
b"
);
break
;
default:
if
(
isprint
(
*
s
))
printf
(
"%c"
,
*
s
);
else
printf
(
"
\\
x%02x"
,(
unsigned
char
)
*
s
);
break
;
}
s
++
;
}
printf
(
"
\"
"
);
}
/*------------------------------------------------------------------------------
/*------------------------------------------------------------------------------
* Networking / parsing
* Networking / parsing
*--------------------------------------------------------------------------- */
*--------------------------------------------------------------------------- */
/* Send AUTH command to the server */
static
int
cliAuth
()
{
redisReply
*
reply
;
if
(
config
.
auth
==
NULL
)
return
REDIS_OK
;
reply
=
redisCommand
(
context
,
"AUTH %s"
,
config
.
auth
);
if
(
reply
!=
NULL
)
{
freeReplyObject
(
reply
);
return
REDIS_OK
;
}
return
REDIS_ERR
;
}
/* Send SELECT dbnum to the server */
static
int
cliSelect
()
{
redisReply
*
reply
;
char
dbnum
[
16
];
if
(
config
.
dbnum
==
0
)
return
REDIS_OK
;
snprintf
(
dbnum
,
sizeof
(
dbnum
),
"%d"
,
config
.
dbnum
);
reply
=
redisCommand
(
context
,
"SELECT %s"
,
dbnum
);
if
(
reply
!=
NULL
)
{
freeReplyObject
(
reply
);
return
REDIS_OK
;
}
return
REDIS_ERR
;
}
/* Connect to the client. If force is not zero the connection is performed
/* Connect to the client. If force is not zero the connection is performed
* even if there is already a connected socket. */
* even if there is already a connected socket. */
static
int
cliConnect
(
int
force
)
{
static
int
cliConnect
(
int
force
)
{
char
err
[
ANET_ERR_LEN
];
if
(
context
==
NULL
||
force
)
{
static
int
fd
=
ANET_ERR
;
if
(
context
!=
NULL
)
redisFree
(
context
);
if
(
fd
==
ANET_ERR
||
force
)
{
if
(
force
)
close
(
fd
);
if
(
config
.
hostsocket
==
NULL
)
{
if
(
config
.
hostsocket
==
NULL
)
{
fd
=
anetTcp
Connect
(
err
,
config
.
hostip
,
config
.
hostport
);
context
=
redis
Connect
(
config
.
hostip
,
config
.
hostport
);
}
else
{
}
else
{
fd
=
anetUnix
Connect
(
err
,
config
.
hostsocket
);
context
=
redis
Connect
Unix
(
config
.
hostsocket
);
}
}
if
(
fd
==
ANET_ERR
)
{
if
(
context
->
err
)
{
fprintf
(
stderr
,
"Could not connect to Redis at "
);
fprintf
(
stderr
,
"Could not connect to Redis at "
);
if
(
config
.
hostsocket
==
NULL
)
if
(
config
.
hostsocket
==
NULL
)
fprintf
(
stderr
,
"%s:%d: %s"
,
config
.
hostip
,
config
.
hostport
,
er
r
);
fprintf
(
stderr
,
"%s:%d: %s
\n
"
,
config
.
hostip
,
config
.
hostport
,
context
->
errst
r
);
else
else
fprintf
(
stderr
,
"%s: %s"
,
config
.
hostsocket
,
err
);
fprintf
(
stderr
,
"%s: %s
\n
"
,
config
.
hostsocket
,
context
->
errstr
);
return
-
1
;
redisFree
(
context
);
context
=
NULL
;
return
REDIS_ERR
;
}
}
anetTcpNoDelay
(
NULL
,
fd
);
}
return
fd
;
}
static
sds
cliReadLine
(
int
fd
)
{
sds
line
=
sdsempty
();
while
(
1
)
{
/* Do AUTH and select the right DB. */
char
c
;
if
(
cliAuth
()
!=
REDIS_OK
)
ssize_t
ret
;
return
REDIS_ERR
;
if
(
cliSelect
()
!=
REDIS_OK
)
ret
=
read
(
fd
,
&
c
,
1
);
return
REDIS_ERR
;
if
(
ret
<=
0
)
{
sdsfree
(
line
);
return
NULL
;
}
else
if
((
ret
==
0
)
||
(
c
==
'\n'
))
{
break
;
}
else
{
line
=
sdscatlen
(
line
,
&
c
,
1
);
}
}
}
return
sdstrim
(
line
,
"
\r\n
"
)
;
return
REDIS_OK
;
}
}
static
int
cliReadSingleLineReply
(
int
fd
,
int
quiet
)
{
static
void
cliPrintContextErrorAndExit
()
{
sds
reply
=
cliReadLine
(
fd
);
if
(
context
==
NULL
)
return
;
fprintf
(
stderr
,
"Error: %s
\n
"
,
context
->
errstr
);
if
(
reply
==
NULL
)
return
1
;
exit
(
1
);
if
(
!
quiet
)
printf
(
"%s"
,
reply
);
sdsfree
(
reply
);
return
0
;
}
}
static
int
cliReadBulkReply
(
int
fd
)
{
static
sds
cliFormatReply
(
redisReply
*
r
,
char
*
prefix
)
{
sds
replylen
=
cliReadLine
(
fd
);
sds
out
=
sdsempty
();
char
*
reply
,
crlf
[
2
];
switch
(
r
->
type
)
{
int
bulklen
;
case
REDIS_REPLY_ERROR
:
out
=
sdscat
(
out
,
prefix
);
if
(
replylen
==
NULL
)
return
1
;
if
(
config
.
tty
)
out
=
sdscat
(
out
,
"(error) "
);
bulklen
=
atoi
(
replylen
);
out
=
sdscatprintf
(
out
,
"%s
\n
"
,
r
->
str
);
if
(
bulklen
==
-
1
)
{
break
;
sdsfree
(
replylen
);
case
REDIS_REPLY_STATUS
:
printf
(
"(nil)
\n
"
);
out
=
sdscat
(
out
,
prefix
);
return
0
;
out
=
sdscat
(
out
,
r
->
str
);
}
out
=
sdscat
(
out
,
"
\n
"
);
reply
=
zmalloc
(
bulklen
);
break
;
anetRead
(
fd
,
reply
,
bulklen
);
case
REDIS_REPLY_INTEGER
:
anetRead
(
fd
,
crlf
,
2
);
out
=
sdscat
(
out
,
prefix
);
if
(
config
.
raw_output
||
!
config
.
tty
)
{
if
(
config
.
tty
)
out
=
sdscat
(
out
,
"(integer) "
);
if
(
bulklen
&&
fwrite
(
reply
,
bulklen
,
1
,
stdout
)
==
0
)
{
out
=
sdscatprintf
(
out
,
"%lld
\n
"
,
r
->
integer
);
zfree
(
reply
);
break
;
return
1
;
case
REDIS_REPLY_STRING
:
out
=
sdscat
(
out
,
prefix
);
if
(
config
.
raw_output
||
!
config
.
tty
)
{
out
=
sdscatlen
(
out
,
r
->
str
,
r
->
len
);
}
else
{
/* If you are producing output for the standard output we want
* a more interesting output with quoted characters and so forth */
out
=
sdscatrepr
(
out
,
r
->
str
,
r
->
len
);
out
=
sdscat
(
out
,
"
\n
"
);
}
}
}
else
{
break
;
/* If you are producing output for the standard output we want
case
REDIS_REPLY_NIL
:
* a more interesting output with quoted characters and so forth */
out
=
sdscat
(
out
,
prefix
);
printStringRepr
(
reply
,
bulklen
);
out
=
sdscat
(
out
,
"(nil)
\n
"
);
}
break
;
zfree
(
reply
);
case
REDIS_REPLY_ARRAY
:
return
0
;
if
(
r
->
elements
==
0
)
{
}
out
=
sdscat
(
out
,
prefix
);
out
=
sdscat
(
out
,
"(empty list or set)
\n
"
);
static
int
cliReadMultiBulkReply
(
int
fd
)
{
sds
replylen
=
cliReadLine
(
fd
);
int
elements
,
c
=
1
;
int
retval
=
0
;
if
(
replylen
==
NULL
)
return
1
;
elements
=
atoi
(
replylen
);
if
(
elements
==
-
1
)
{
sdsfree
(
replylen
);
printf
(
"(nil)
\n
"
);
return
0
;
}
if
(
elements
==
0
)
{
printf
(
"(empty list or set)
\n
"
);
}
while
(
elements
--
)
{
if
(
config
.
tty
)
printf
(
"%d. "
,
c
);
if
(
cliReadReply
(
fd
))
retval
=
1
;
if
(
elements
)
printf
(
"%c"
,
config
.
mb_sep
);
c
++
;
}
return
retval
;
}
static
int
cliReadReply
(
int
fd
)
{
char
type
;
int
nread
;
if
((
nread
=
anetRead
(
fd
,
&
type
,
1
))
<=
0
)
{
if
(
config
.
shutdown
)
return
0
;
if
(
config
.
interactive
&&
(
nread
==
0
||
(
nread
==
-
1
&&
errno
==
ECONNRESET
)))
{
return
ECONNRESET
;
}
else
{
}
else
{
printf
(
"I/O error while reading from socket: %s"
,
strerror
(
errno
));
unsigned
int
i
;
exit
(
1
);
sds
tmp
;
for
(
i
=
0
;
i
<
r
->
elements
;
i
++
)
{
tmp
=
cliFormatReply
(
r
->
element
[
i
],
prefix
);
out
=
sdscat
(
out
,
prefix
);
out
=
sdscatlen
(
out
,
tmp
,
sdslen
(
tmp
));
sdsfree
(
tmp
);
}
}
}
}
break
;
switch
(
type
)
{
case
'-'
:
if
(
config
.
tty
)
printf
(
"(error) "
);
cliReadSingleLineReply
(
fd
,
0
);
return
1
;
case
'+'
:
return
cliReadSingleLineReply
(
fd
,
0
);
case
':'
:
if
(
config
.
tty
)
printf
(
"(integer) "
);
return
cliReadSingleLineReply
(
fd
,
0
);
case
'$'
:
return
cliReadBulkReply
(
fd
);
case
'*'
:
return
cliReadMultiBulkReply
(
fd
);
default:
default:
printf
(
"protocol error, got '%c' as reply type byte"
,
type
);
f
printf
(
stderr
,
"Unknown reply type: %d
\n
"
,
r
->
type
);
return
1
;
exit
(
1
)
;
}
}
return
out
;
}
}
static
int
selectDb
(
int
fd
)
{
static
int
cliReadReply
(
)
{
int
retval
;
redisReply
*
reply
;
sds
cmd
;
sds
out
;
char
type
;
if
(
redisGetReply
(
context
,(
void
**
)
&
reply
)
!=
REDIS_OK
)
{
if
(
config
.
dbnum
==
0
)
if
(
config
.
shutdown
)
return
0
;
return
REDIS_OK
;
if
(
config
.
interactive
)
{
cmd
=
sdsempty
();
/* Filter cases where we should reconnect */
cmd
=
sdscatprintf
(
cmd
,
"SELECT %d
\r\n
"
,
config
.
dbnum
);
if
(
context
->
err
==
REDIS_ERR_IO
&&
errno
==
ECONNRESET
)
anetWrite
(
fd
,
cmd
,
sdslen
(
cmd
))
;
return
REDIS_ERR
;
anetRead
(
fd
,
&
type
,
1
);
if
(
context
->
err
==
REDIS_ERR_EOF
)
if
(
type
<=
0
||
type
!=
'+'
)
return
1
;
return
REDIS_ERR
;
retval
=
cliReadSingleLineReply
(
fd
,
1
);
}
if
(
retval
)
{
cliPrintContextErrorAndExit
();
return
retval
;
return
REDIS_ERR
;
/* avoid compiler warning */
}
}
return
0
;
out
=
cliFormatReply
(
reply
,
""
);
freeReplyObject
(
reply
);
fwrite
(
out
,
sdslen
(
out
),
1
,
stdout
);
sdsfree
(
out
);
return
REDIS_OK
;
}
}
static
void
showInteractiveHelp
(
void
)
{
static
void
showInteractiveHelp
(
void
)
{
...
@@ -294,56 +252,41 @@ static void showInteractiveHelp(void) {
...
@@ -294,56 +252,41 @@ static void showInteractiveHelp(void) {
static
int
cliSendCommand
(
int
argc
,
char
**
argv
,
int
repeat
)
{
static
int
cliSendCommand
(
int
argc
,
char
**
argv
,
int
repeat
)
{
char
*
command
=
argv
[
0
];
char
*
command
=
argv
[
0
];
int
fd
,
j
,
retval
=
0
;
size_t
*
argvlen
;
sds
cmd
;
int
j
;
config
.
raw_output
=
!
strcasecmp
(
command
,
"info"
);
config
.
raw_output
=
!
strcasecmp
(
command
,
"info"
);
if
(
!
strcasecmp
(
command
,
"help"
))
{
if
(
!
strcasecmp
(
command
,
"help"
))
{
showInteractiveHelp
();
showInteractiveHelp
();
return
0
;
return
REDIS_OK
;
}
}
if
(
!
strcasecmp
(
command
,
"shutdown"
))
config
.
shutdown
=
1
;
if
(
!
strcasecmp
(
command
,
"shutdown"
))
config
.
shutdown
=
1
;
if
(
!
strcasecmp
(
command
,
"monitor"
))
config
.
monitor_mode
=
1
;
if
(
!
strcasecmp
(
command
,
"monitor"
))
config
.
monitor_mode
=
1
;
if
(
!
strcasecmp
(
command
,
"subscribe"
)
||
if
(
!
strcasecmp
(
command
,
"subscribe"
)
||
!
strcasecmp
(
command
,
"psubscribe"
))
config
.
pubsub_mode
=
1
;
!
strcasecmp
(
command
,
"psubscribe"
))
config
.
pubsub_mode
=
1
;
if
((
fd
=
cliConnect
(
0
))
==
-
1
)
return
1
;
/* Select db number */
/* Setup argument length */
retval
=
selectDb
(
fd
);
argvlen
=
malloc
(
argc
*
sizeof
(
size_t
));
if
(
retval
)
{
for
(
j
=
0
;
j
<
argc
;
j
++
)
fprintf
(
stderr
,
"Error setting DB num
\n
"
);
argvlen
[
j
]
=
sdslen
(
argv
[
j
]);
return
1
;
}
/* Build the command to send */
cmd
=
sdscatprintf
(
sdsempty
(),
"*%d
\r\n
"
,
argc
);
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
cmd
=
sdscatprintf
(
cmd
,
"$%lu
\r\n
"
,
(
unsigned
long
)
sdslen
(
argv
[
j
]));
cmd
=
sdscatlen
(
cmd
,
argv
[
j
],
sdslen
(
argv
[
j
]));
cmd
=
sdscatlen
(
cmd
,
"
\r\n
"
,
2
);
}
while
(
repeat
--
)
{
while
(
repeat
--
)
{
anetWrite
(
fd
,
cmd
,
sdslen
(
cmd
)
);
redisAppendCommandArgv
(
context
,
argc
,(
const
char
**
)
argv
,
argvlen
);
while
(
config
.
monitor_mode
)
{
while
(
config
.
monitor_mode
)
{
if
(
cliReadSingleLineReply
(
fd
,
0
))
exit
(
1
);
if
(
cliReadReply
()
!=
REDIS_OK
)
exit
(
1
);
printf
(
"
\n
"
);
}
}
if
(
config
.
pubsub_mode
)
{
if
(
config
.
pubsub_mode
)
{
printf
(
"Reading messages... (press Ctrl-
c
to quit)
\n
"
);
printf
(
"Reading messages... (press Ctrl-
C
to quit)
\n
"
);
while
(
1
)
{
while
(
1
)
{
cliReadReply
(
fd
);
if
(
cliReadReply
()
!=
REDIS_OK
)
exit
(
1
);
printf
(
"
\n\n
"
);
}
}
}
}
retval
=
cliReadReply
(
fd
);
if
(
cliReadReply
()
!=
REDIS_OK
)
if
(
!
config
.
raw_output
&&
config
.
tty
)
printf
(
"
\n
"
);
return
REDIS_ERR
;
if
(
retval
)
return
retval
;
}
}
return
0
;
return
REDIS_OK
;
}
}
/*------------------------------------------------------------------------------
/*------------------------------------------------------------------------------
...
@@ -357,12 +300,7 @@ static int parseOptions(int argc, char **argv) {
...
@@ -357,12 +300,7 @@ static int parseOptions(int argc, char **argv) {
int
lastarg
=
i
==
argc
-
1
;
int
lastarg
=
i
==
argc
-
1
;
if
(
!
strcmp
(
argv
[
i
],
"-h"
)
&&
!
lastarg
)
{
if
(
!
strcmp
(
argv
[
i
],
"-h"
)
&&
!
lastarg
)
{
char
*
ip
=
zmalloc
(
32
);
config
.
hostip
=
argv
[
i
+
1
];
if
(
anetResolve
(
NULL
,
argv
[
i
+
1
],
ip
)
==
ANET_ERR
)
{
printf
(
"Can't resolve %s
\n
"
,
argv
[
i
]);
exit
(
1
);
}
config
.
hostip
=
ip
;
i
++
;
i
++
;
}
else
if
(
!
strcmp
(
argv
[
i
],
"-h"
)
&&
lastarg
)
{
}
else
if
(
!
strcmp
(
argv
[
i
],
"-h"
)
&&
lastarg
)
{
usage
();
usage
();
...
@@ -463,17 +401,18 @@ static void repl() {
...
@@ -463,17 +401,18 @@ static void repl() {
{
{
exit
(
0
);
exit
(
0
);
}
else
{
}
else
{
int
err
;
long
long
start_time
=
mstime
(),
elapsed
;
long
long
start_time
=
mstime
(),
elapsed
;
if
((
err
=
cliSendCommand
(
argc
,
argv
,
1
))
!=
0
)
{
if
(
cliSendCommand
(
argc
,
argv
,
1
)
!=
REDIS_OK
)
{
if
(
err
==
ECONNRESET
)
{
printf
(
"Reconnecting... "
);
printf
(
"Reconnecting... "
);
fflush
(
stdout
);
fflush
(
stdout
);
if
(
cliConnect
(
1
)
!=
REDIS_OK
)
exit
(
1
);
if
(
cliConnect
(
1
)
==
-
1
)
exit
(
1
);
printf
(
"OK
\n
"
);
printf
(
"OK
\n
"
);
cliSendCommand
(
argc
,
argv
,
1
);
/* If we still cannot send the command,
}
* print error and abort. */
if
(
cliSendCommand
(
argc
,
argv
,
1
)
!=
REDIS_OK
)
cliPrintContextErrorAndExit
();
}
}
elapsed
=
mstime
()
-
start_time
;
elapsed
=
mstime
()
-
start_time
;
if
(
elapsed
>
500
)
printf
(
"%.2f seconds
\n
"
,
if
(
elapsed
>
500
)
printf
(
"%.2f seconds
\n
"
,
...
@@ -533,19 +472,8 @@ int main(int argc, char **argv) {
...
@@ -533,19 +472,8 @@ int main(int argc, char **argv) {
argc
-=
firstarg
;
argc
-=
firstarg
;
argv
+=
firstarg
;
argv
+=
firstarg
;
if
(
config
.
auth
!=
NULL
)
{
/* Try to connect */
char
*
authargv
[
2
];
if
(
cliConnect
(
0
)
!=
REDIS_OK
)
exit
(
1
);
int
dbnum
=
config
.
dbnum
;
/* We need to save the real configured database number and set it to
* zero here, otherwise cliSendCommand() will try to perform the
* SELECT command before the authentication, and it will fail. */
config
.
dbnum
=
0
;
authargv
[
0
]
=
"AUTH"
;
authargv
[
1
]
=
config
.
auth
;
cliSendCommand
(
2
,
convertToSds
(
2
,
authargv
),
1
);
config
.
dbnum
=
dbnum
;
/* restore the right DB number */
}
/* Start interactive mode when no command is provided */
/* Start interactive mode when no command is provided */
if
(
argc
==
0
)
repl
();
if
(
argc
==
0
)
repl
();
...
...
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