Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
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