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
adfaf548
Unverified
Commit
adfaf548
authored
Jan 21, 2019
by
Salvatore Sanfilippo
Committed by
GitHub
Jan 21, 2019
Browse files
Merge branch 'unstable' into fixChildInfoPipeFdLeak
parents
440385de
cfdc800a
Changes
54
Expand all
Show whitespace changes
Inline
Side-by-side
src/sentinel.c
View file @
adfaf548
...
...
@@ -453,7 +453,8 @@ struct redisCommand sentinelcmds[] = {
{
"role"
,
sentinelRoleCommand
,
1
,
"l"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"client"
,
clientCommand
,
-
2
,
"rs"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"shutdown"
,
shutdownCommand
,
-
1
,
""
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{"auth",authCommand,2,"sltF",0,NULL,0,0,0,0,0}
{
"auth"
,
authCommand
,
2
,
"sltF"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
},
{
"hello"
,
helloCommand
,
-
2
,
"sF"
,
0
,
NULL
,
0
,
0
,
0
,
0
,
0
}
};
/* This function overwrites a few normal Redis config default with Sentinel
...
...
@@ -885,17 +886,17 @@ void sentinelPendingScriptsCommand(client *c) {
listNode
*
ln
;
listIter
li
;
addReply
MultiBulk
Len(c,listLength(sentinel.scripts_queue));
addReply
Array
Len
(
c
,
listLength
(
sentinel
.
scripts_queue
));
listRewind
(
sentinel
.
scripts_queue
,
&
li
);
while
((
ln
=
listNext
(
&
li
))
!=
NULL
)
{
sentinelScriptJob
*
sj
=
ln
->
value
;
int
j
=
0
;
addReplyM
ultiBulk
Len(c,
10
);
addReplyM
ap
Len
(
c
,
5
);
addReplyBulkCString
(
c
,
"argv"
);
while
(
sj
->
argv
[
j
])
j
++
;
addReply
MultiBulk
Len(c,j);
addReply
Array
Len
(
c
,
j
);
j
=
0
;
while
(
sj
->
argv
[
j
])
addReplyBulkCString
(
c
,
sj
->
argv
[
j
++
]);
...
...
@@ -1960,7 +1961,7 @@ void sentinelSendAuthIfNeeded(sentinelRedisInstance *ri, redisAsyncContext *c) {
}
else
if
(
ri
->
flags
&
SRI_SLAVE
)
{
auth_pass
=
ri
->
master
->
auth_pass
;
}
else
if
(
ri
->
flags
&
SRI_SENTINEL
)
{
if (server.requirepass) auth_pass = server.requirepass
;
auth_pass
=
ACLDefaultUserFirstPassword
()
;
}
if
(
auth_pass
)
{
...
...
@@ -2741,7 +2742,7 @@ void addReplySentinelRedisInstance(client *c, sentinelRedisInstance *ri) {
void
*
mbl
;
int
fields
=
0
;
mbl = addDeferred
MultiBulkLength
(c);
mbl
=
add
Reply
Deferred
Len
(
c
);
addReplyBulkCString
(
c
,
"name"
);
addReplyBulkCString
(
c
,
ri
->
name
);
...
...
@@ -2922,7 +2923,7 @@ void addReplySentinelRedisInstance(client *c, sentinelRedisInstance *ri) {
fields
++
;
}
setDeferredM
ultiBulkLength
(c,mbl,fields
*2
);
setDeferredM
apLen
(
c
,
mbl
,
fields
);
}
/* Output a number of instances contained inside a dictionary as
...
...
@@ -2932,7 +2933,7 @@ void addReplyDictOfRedisInstances(client *c, dict *instances) {
dictEntry
*
de
;
di
=
dictGetIterator
(
instances
);
addReply
MultiBulk
Len(c,dictSize(instances));
addReply
Array
Len
(
c
,
dictSize
(
instances
));
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
sentinelRedisInstance
*
ri
=
dictGetVal
(
de
);
...
...
@@ -3062,7 +3063,7 @@ void sentinelCommand(client *c) {
/* Reply with a three-elements multi-bulk reply:
* down state, leader, vote epoch. */
addReply
MultiBulk
Len(c,3);
addReply
Array
Len
(
c
,
3
);
addReply
(
c
,
isdown
?
shared
.
cone
:
shared
.
czero
);
addReplyBulkCString
(
c
,
leader
?
leader
:
"*"
);
addReplyLongLong
(
c
,
(
long
long
)
leader_epoch
);
...
...
@@ -3078,11 +3079,11 @@ void sentinelCommand(client *c) {
if
(
c
->
argc
!=
3
)
goto
numargserr
;
ri
=
sentinelGetMasterByName
(
c
->
argv
[
2
]
->
ptr
);
if
(
ri
==
NULL
)
{
addReply
(c,shared.nullmultibulk
);
addReply
NullArray
(
c
);
}
else
{
sentinelAddr
*
addr
=
sentinelGetCurrentMasterAddress
(
ri
);
addReply
MultiBulk
Len(c,2);
addReply
Array
Len
(
c
,
2
);
addReplyBulkCString
(
c
,
addr
->
ip
);
addReplyBulkLongLong
(
c
,
addr
->
port
);
}
...
...
@@ -3232,7 +3233,7 @@ void sentinelCommand(client *c) {
* 3.) other master name
* ...
*/
addReply
MultiBulk
Len(c,dictSize(masters_local) * 2);
addReply
Array
Len
(
c
,
dictSize
(
masters_local
)
*
2
);
dictIterator
*
di
;
dictEntry
*
de
;
...
...
@@ -3240,25 +3241,25 @@ void sentinelCommand(client *c) {
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
sentinelRedisInstance
*
ri
=
dictGetVal
(
de
);
addReplyBulkCBuffer
(
c
,
ri
->
name
,
strlen
(
ri
->
name
));
addReply
MultiBulk
Len(c,dictSize(ri->slaves) + 1); /* +1 for self */
addReply
MultiBulk
Len(c,2);
addReply
Array
Len
(
c
,
dictSize
(
ri
->
slaves
)
+
1
);
/* +1 for self */
addReply
Array
Len
(
c
,
2
);
addReplyLongLong
(
c
,
now
-
ri
->
info_refresh
);
if
(
ri
->
info
)
addReplyBulkCBuffer
(
c
,
ri
->
info
,
sdslen
(
ri
->
info
));
else
addReply
(c,shared.nullbulk
);
addReply
Null
(
c
);
dictIterator
*
sdi
;
dictEntry
*
sde
;
sdi
=
dictGetIterator
(
ri
->
slaves
);
while
((
sde
=
dictNext
(
sdi
))
!=
NULL
)
{
sentinelRedisInstance
*
sri
=
dictGetVal
(
sde
);
addReply
MultiBulk
Len(c,2);
addReply
Array
Len
(
c
,
2
);
addReplyLongLong
(
c
,
now
-
sri
->
info_refresh
);
if
(
sri
->
info
)
addReplyBulkCBuffer
(
c
,
sri
->
info
,
sdslen
(
sri
->
info
));
else
addReply
(c,shared.nullbulk
);
addReply
Null
(
c
);
}
dictReleaseIterator
(
sdi
);
}
...
...
@@ -3282,7 +3283,7 @@ void sentinelCommand(client *c) {
serverLog
(
LL_WARNING
,
"Failure simulation: this Sentinel "
"will crash after promoting the selected replica to master"
);
}
else
if
(
!
strcasecmp
(
c
->
argv
[
j
]
->
ptr
,
"help"
))
{
addReply
MultiBulk
Len(c,2);
addReply
Array
Len
(
c
,
2
);
addReplyBulkCString
(
c
,
"crash-after-election"
);
addReplyBulkCString
(
c
,
"crash-after-promotion"
);
}
else
{
...
...
@@ -3382,9 +3383,9 @@ void sentinelRoleCommand(client *c) {
dictIterator
*
di
;
dictEntry
*
de
;
addReply
MultiBulk
Len(c,2);
addReply
Array
Len
(
c
,
2
);
addReplyBulkCBuffer
(
c
,
"sentinel"
,
8
);
addReply
MultiBulk
Len(c,dictSize(sentinel.masters));
addReply
Array
Len
(
c
,
dictSize
(
sentinel
.
masters
));
di
=
dictGetIterator
(
sentinel
.
masters
);
while
((
de
=
dictNext
(
di
))
!=
NULL
)
{
...
...
src/server.c
View file @
adfaf548
This diff is collapsed.
Click to expand it.
src/server.h
View file @
adfaf548
...
...
@@ -707,11 +707,51 @@ typedef struct readyList {
robj
*
key
;
}
readyList
;
/* This structure represents a Redis user. This is useful for ACLs, the
* user is associated to the connection after the connection is authenticated.
* If there is no associated user, the connection uses the default user. */
#define USER_MAX_COMMAND_BIT 1024
/* The first *not valid* bit that
would overflow. So check for >= */
#define USER_FLAG_ENABLED (1<<0)
/* The user is active. */
#define USER_FLAG_ALLKEYS (1<<1)
/* The user can mention any key. */
#define USER_FLAG_ALLCOMMANDS (1<<2)
/* The user can run all commands. */
#define USER_FLAG_NOPASS (1<<3)
/* The user requires no password, any
provided password will work. For the
default user, this also means that
no AUTH is needed, and every
connection is immediately
authenticated. */
typedef
struct
user
{
sds
name
;
/* The username as an SDS string. */
uint64_t
flags
;
/* See USER_FLAG_* */
/* The bit in allowed_commands is set if this user has the right to
* execute this command. In commands having subcommands, if this bit is
* set, then all the subcommands are also available.
*
* If the bit for a given command is NOT set and the command has
* subcommands, Redis will also check allowed_subcommands in order to
* understand if the command can be executed. */
uint64_t
allowed_commands
[
USER_MAX_COMMAND_BIT
/
64
];
/* This array points, for each command ID (corresponding to the command
* bit set in allowed_commands), to an array of SDS strings, terminated by
* a NULL pointer, with all the sub commands that can be executed for
* this command. When no subcommands matching is used, the field is just
* set to NULL to avoid allocating USER_MAX_COMMAND_BIT pointers. */
sds
**
allowed_subcommands
;
list
*
passwords
;
/* A list of SDS valid passwords for this user. */
list
*
patterns
;
/* A list of allowed key patterns. If this field is NULL
the user cannot mention any key in a command, unless
the flag ALLKEYS is set in the user. */
}
user
;
/* With multiplexing we need to take per-client state.
* Clients are taken in a linked list. */
typedef
struct
client
{
uint64_t
id
;
/* Client incremental unique ID. */
int
fd
;
/* Client socket. */
int
resp
;
/* RESP protocol version. Can be 2 or 3. */
redisDb
*
db
;
/* Pointer to currently SELECTed DB. */
robj
*
name
;
/* As set by CLIENT SETNAME. */
sds
querybuf
;
/* Buffer we use to accumulate client queries. */
...
...
@@ -724,6 +764,9 @@ typedef struct client {
int
argc
;
/* Num of arguments of current command. */
robj
**
argv
;
/* Arguments of current command. */
struct
redisCommand
*
cmd
,
*
lastcmd
;
/* Last command executed. */
user
*
user
;
/* User associated with this connection. If the
user is set to NULL the connection can do
anything (admin). */
int
reqtype
;
/* Request protocol type: PROTO_REQ_* */
int
multibulklen
;
/* Number of multi bulk arguments left to read. */
long
bulklen
;
/* Length of bulk argument in multi bulk request. */
...
...
@@ -735,7 +778,7 @@ typedef struct client {
time_t
lastinteraction
;
/* Time of the last interaction, used for timeout */
time_t
obuf_soft_limit_reached_time
;
int
flags
;
/* Client flags: CLIENT_* macros. */
int
authenticated
;
/*
When requirepass is non-NULL
. */
int
authenticated
;
/*
Needed when the default user requires auth
. */
int
replstate
;
/* Replication state if this is a slave. */
int
repl_put_online_on_ack
;
/* Install slave write handler on ACK. */
int
repldbfd
;
/* Replication DB file descriptor. */
...
...
@@ -780,9 +823,9 @@ struct moduleLoadQueueEntry {
};
struct
sharedObjectsStruct
{
robj
*
crlf
,
*
ok
,
*
err
,
*
emptybulk
,
*
czero
,
*
cone
,
*
cnegone
,
*
pong
,
*
space
,
*
colon
,
*
nullbulk
,
*
nullmultibulk
,
*
queued
,
*
empty
multibulk
,
*
wrongtypeerr
,
*
nokeyerr
,
*
syntaxerr
,
*
sameobjecterr
,
robj
*
crlf
,
*
ok
,
*
err
,
*
emptybulk
,
*
czero
,
*
cone
,
*
pong
,
*
space
,
*
colon
,
*
queued
,
*
null
[
4
],
*
nullarray
[
4
]
,
*
empty
array
,
*
wrongtypeerr
,
*
nokeyerr
,
*
syntaxerr
,
*
sameobjecterr
,
*
outofrangeerr
,
*
noscripterr
,
*
loadingerr
,
*
slowscripterr
,
*
bgsaveerr
,
*
masterdownerr
,
*
roslaveerr
,
*
execaborterr
,
*
noautherr
,
*
noreplicaserr
,
*
busykeyerr
,
*
oomerr
,
*
plus
,
*
messagebulk
,
*
pmessagebulk
,
*
subscribebulk
,
...
...
@@ -945,7 +988,6 @@ struct redisServer {
int
shutdown_asap
;
/* SHUTDOWN needed ASAP */
int
activerehashing
;
/* Incremental rehash in serverCron() */
int
active_defrag_running
;
/* Active defragmentation running (holds current scan aggressiveness) */
char
*
requirepass
;
/* Pass for AUTH command, or NULL */
char
*
pidfile
;
/* PID file path */
int
arch_bits
;
/* 32 or 64 depending on sizeof(long) */
int
cronloops
;
/* Number of times the cron function run */
...
...
@@ -1304,6 +1346,11 @@ struct redisCommand {
int
lastkey
;
/* The last argument that's a key */
int
keystep
;
/* The step between first and last key */
long
long
microseconds
,
calls
;
int
id
;
/* Command ID. This is a progressive ID starting from 0 that
is assigned at runtime, and is used in order to check
ACLs. A connection is able to execute a given command if
the user associated to the connection has this command
bit set in the bitmap of allowed commands. */
};
struct
redisFunctionSym
{
...
...
@@ -1424,15 +1471,23 @@ void freeClient(client *c);
void
freeClientAsync
(
client
*
c
);
void
resetClient
(
client
*
c
);
void
sendReplyToClient
(
aeEventLoop
*
el
,
int
fd
,
void
*
privdata
,
int
mask
);
void
*
addDeferredMultiBulkLength
(
client
*
c
);
void
setDeferredMultiBulkLength
(
client
*
c
,
void
*
node
,
long
length
);
void
*
addReplyDeferredLen
(
client
*
c
);
void
setDeferredArrayLen
(
client
*
c
,
void
*
node
,
long
length
);
void
setDeferredMapLen
(
client
*
c
,
void
*
node
,
long
length
);
void
setDeferredSetLen
(
client
*
c
,
void
*
node
,
long
length
);
void
setDeferredAttributeLen
(
client
*
c
,
void
*
node
,
long
length
);
void
setDeferredPushLen
(
client
*
c
,
void
*
node
,
long
length
);
void
processInputBuffer
(
client
*
c
);
void
processInputBufferAndReplicate
(
client
*
c
);
void
acceptHandler
(
aeEventLoop
*
el
,
int
fd
,
void
*
privdata
,
int
mask
);
void
acceptTcpHandler
(
aeEventLoop
*
el
,
int
fd
,
void
*
privdata
,
int
mask
);
void
acceptUnixHandler
(
aeEventLoop
*
el
,
int
fd
,
void
*
privdata
,
int
mask
);
void
readQueryFromClient
(
aeEventLoop
*
el
,
int
fd
,
void
*
privdata
,
int
mask
);
void
addReplyString
(
client
*
c
,
const
char
*
s
,
size_t
len
);
void
addReplyNull
(
client
*
c
);
void
addReplyNullArray
(
client
*
c
);
void
addReplyBool
(
client
*
c
,
int
b
);
void
addReplyVerbatim
(
client
*
c
,
const
char
*
s
,
size_t
len
,
const
char
*
ext
);
void
addReplyProto
(
client
*
c
,
const
char
*
s
,
size_t
len
);
void
addReplyBulk
(
client
*
c
,
robj
*
obj
);
void
addReplyBulkCString
(
client
*
c
,
const
char
*
s
);
void
addReplyBulkCBuffer
(
client
*
c
,
const
void
*
p
,
size_t
len
);
...
...
@@ -1445,9 +1500,14 @@ void addReplyStatus(client *c, const char *status);
void
addReplyDouble
(
client
*
c
,
double
d
);
void
addReplyHumanLongDouble
(
client
*
c
,
long
double
d
);
void
addReplyLongLong
(
client
*
c
,
long
long
ll
);
void
addReplyMultiBulkLen
(
client
*
c
,
long
length
);
void
addReplyArrayLen
(
client
*
c
,
long
length
);
void
addReplyMapLen
(
client
*
c
,
long
length
);
void
addReplySetLen
(
client
*
c
,
long
length
);
void
addReplyAttributeLen
(
client
*
c
,
long
length
);
void
addReplyPushLen
(
client
*
c
,
long
length
);
void
addReplyHelp
(
client
*
c
,
const
char
**
help
);
void
addReplySubcommandSyntaxError
(
client
*
c
);
void
addReplyLoadedModules
(
client
*
c
);
void
copyClientOutputBuffer
(
client
*
dst
,
client
*
src
);
size_t
sdsZmallocSize
(
sds
s
);
size_t
getStringObjectSdsUsedMemory
(
robj
*
o
);
...
...
@@ -1634,6 +1694,20 @@ void closeChildInfoPipe(void);
void
sendChildInfo
(
int
process_type
);
void
receiveChildInfo
(
void
);
/* acl.c -- Authentication related prototypes. */
extern
user
*
DefaultUser
;
void
ACLInit
(
void
);
/* Return values for ACLCheckUserCredentials(). */
#define ACL_OK 0
#define ACL_DENIED_CMD 1
#define ACL_DENIED_KEY 2
int
ACLCheckUserCredentials
(
robj
*
username
,
robj
*
password
);
unsigned
long
ACLGetCommandID
(
const
char
*
cmdname
);
user
*
ACLGetUserByName
(
const
char
*
name
,
size_t
namelen
);
int
ACLCheckCommandPerm
(
client
*
c
);
int
ACLSetUser
(
user
*
u
,
const
char
*
op
,
ssize_t
oplen
);
sds
ACLDefaultUserFirstPassword
(
void
);
/* Sorted sets data type */
/* Input flags. */
...
...
@@ -2082,6 +2156,7 @@ void dumpCommand(client *c);
void
objectCommand
(
client
*
c
);
void
memoryCommand
(
client
*
c
);
void
clientCommand
(
client
*
c
);
void
helloCommand
(
client
*
c
);
void
evalCommand
(
client
*
c
);
void
evalShaCommand
(
client
*
c
);
void
scriptCommand
(
client
*
c
);
...
...
@@ -2123,6 +2198,7 @@ void xinfoCommand(client *c);
void
xdelCommand
(
client
*
c
);
void
xtrimCommand
(
client
*
c
);
void
lolwutCommand
(
client
*
c
);
void
aclCommand
(
client
*
c
);
#if defined(__GNUC__)
void
*
calloc
(
size_t
count
,
size_t
size
)
__attribute__
((
deprecated
));
...
...
src/slowlog.c
View file @
adfaf548
...
...
@@ -169,23 +169,23 @@ NULL
return
;
listRewind
(
server
.
slowlog
,
&
li
);
totentries
=
addDeferred
MultiBulkLength
(
c
);
totentries
=
add
Reply
Deferred
Len
(
c
);
while
(
count
--
&&
(
ln
=
listNext
(
&
li
)))
{
int
j
;
se
=
ln
->
value
;
addReply
MultiBulk
Len
(
c
,
6
);
addReply
Array
Len
(
c
,
6
);
addReplyLongLong
(
c
,
se
->
id
);
addReplyLongLong
(
c
,
se
->
time
);
addReplyLongLong
(
c
,
se
->
duration
);
addReply
MultiBulk
Len
(
c
,
se
->
argc
);
addReply
Array
Len
(
c
,
se
->
argc
);
for
(
j
=
0
;
j
<
se
->
argc
;
j
++
)
addReplyBulk
(
c
,
se
->
argv
[
j
]);
addReplyBulkCBuffer
(
c
,
se
->
peerid
,
sdslen
(
se
->
peerid
));
addReplyBulkCBuffer
(
c
,
se
->
cname
,
sdslen
(
se
->
cname
));
sent
++
;
}
setDeferred
MultiBulkLength
(
c
,
totentries
,
sent
);
setDeferred
ArrayLen
(
c
,
totentries
,
sent
);
}
else
{
addReplySubcommandSyntaxError
(
c
);
}
...
...
src/sort.c
View file @
adfaf548
...
...
@@ -505,7 +505,7 @@ void sortCommand(client *c) {
addReplyError
(
c
,
"One or more scores can't be converted into double"
);
}
else
if
(
storekey
==
NULL
)
{
/* STORE option not specified, sent the sorting result to client */
addReply
MultiBulk
Len
(
c
,
outputlen
);
addReply
Array
Len
(
c
,
outputlen
);
for
(
j
=
start
;
j
<=
end
;
j
++
)
{
listNode
*
ln
;
listIter
li
;
...
...
@@ -519,7 +519,7 @@ void sortCommand(client *c) {
if
(
sop
->
type
==
SORT_OP_GET
)
{
if
(
!
val
)
{
addReply
(
c
,
shared
.
nullbulk
);
addReply
Null
(
c
);
}
else
{
addReplyBulk
(
c
,
val
);
decrRefCount
(
val
);
...
...
src/t_hash.c
View file @
adfaf548
...
...
@@ -641,7 +641,7 @@ static void addHashFieldToReply(client *c, robj *o, sds field) {
int
ret
;
if
(
o
==
NULL
)
{
addReply
(
c
,
shared
.
nullbulk
);
addReply
Null
(
c
);
return
;
}
...
...
@@ -652,7 +652,7 @@ static void addHashFieldToReply(client *c, robj *o, sds field) {
ret
=
hashTypeGetFromZiplist
(
o
,
field
,
&
vstr
,
&
vlen
,
&
vll
);
if
(
ret
<
0
)
{
addReply
(
c
,
shared
.
nullbulk
);
addReply
Null
(
c
);
}
else
{
if
(
vstr
)
{
addReplyBulkCBuffer
(
c
,
vstr
,
vlen
);
...
...
@@ -664,7 +664,7 @@ static void addHashFieldToReply(client *c, robj *o, sds field) {
}
else
if
(
o
->
encoding
==
OBJ_ENCODING_HT
)
{
sds
value
=
hashTypeGetFromHashTable
(
o
,
field
);
if
(
value
==
NULL
)
addReply
(
c
,
shared
.
nullbulk
);
addReply
Null
(
c
);
else
addReplyBulkCBuffer
(
c
,
value
,
sdslen
(
value
));
}
else
{
...
...
@@ -675,7 +675,7 @@ static void addHashFieldToReply(client *c, robj *o, sds field) {
void
hgetCommand
(
client
*
c
)
{
robj
*
o
;
if
((
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
null
bulk
))
==
NULL
||
if
((
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
null
[
c
->
resp
]
))
==
NULL
||
checkType
(
c
,
o
,
OBJ_HASH
))
return
;
addHashFieldToReply
(
c
,
o
,
c
->
argv
[
2
]
->
ptr
);
...
...
@@ -693,7 +693,7 @@ void hmgetCommand(client *c) {
return
;
}
addReply
MultiBulk
Len
(
c
,
c
->
argc
-
2
);
addReply
Array
Len
(
c
,
c
->
argc
-
2
);
for
(
i
=
2
;
i
<
c
->
argc
;
i
++
)
{
addHashFieldToReply
(
c
,
o
,
c
->
argv
[
i
]
->
ptr
);
}
...
...
@@ -766,17 +766,19 @@ static void addHashIteratorCursorToReply(client *c, hashTypeIterator *hi, int wh
void
genericHgetallCommand
(
client
*
c
,
int
flags
)
{
robj
*
o
;
hashTypeIterator
*
hi
;
int
multiplier
=
0
;
int
length
,
count
=
0
;
if
((
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
emptymultibulk
))
==
NULL
if
((
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
null
[
c
->
resp
]
))
==
NULL
||
checkType
(
c
,
o
,
OBJ_HASH
))
return
;
if
(
flags
&
OBJ_HASH_KEY
)
multiplier
++
;
if
(
flags
&
OBJ_HASH_VALUE
)
multiplier
++
;
length
=
hashTypeLength
(
o
)
*
multiplier
;
addReplyMultiBulkLen
(
c
,
length
);
/* We return a map if the user requested keys and values, like in the
* HGETALL case. Otherwise to use a flat array makes more sense. */
length
=
hashTypeLength
(
o
);
if
(
flags
&
OBJ_HASH_KEY
&&
flags
&
OBJ_HASH_VALUE
)
{
addReplyMapLen
(
c
,
length
);
}
else
{
addReplyArrayLen
(
c
,
length
);
}
hi
=
hashTypeInitIterator
(
o
);
while
(
hashTypeNext
(
hi
)
!=
C_ERR
)
{
...
...
@@ -791,6 +793,9 @@ void genericHgetallCommand(client *c, int flags) {
}
hashTypeReleaseIterator
(
hi
);
/* Make sure we returned the right number of elements. */
if
(
flags
&
OBJ_HASH_KEY
&&
flags
&
OBJ_HASH_VALUE
)
count
/=
2
;
serverAssert
(
count
==
length
);
}
...
...
src/t_list.c
View file @
adfaf548
...
...
@@ -298,7 +298,7 @@ void linsertCommand(client *c) {
server
.
dirty
++
;
}
else
{
/* Notify client of a failed insert */
addReply
(
c
,
shared
.
cnegone
);
addReply
LongLong
(
c
,
-
1
);
return
;
}
...
...
@@ -312,7 +312,7 @@ void llenCommand(client *c) {
}
void
lindexCommand
(
client
*
c
)
{
robj
*
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
null
bulk
);
robj
*
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
null
[
c
->
resp
]
);
if
(
o
==
NULL
||
checkType
(
c
,
o
,
OBJ_LIST
))
return
;
long
index
;
robj
*
value
=
NULL
;
...
...
@@ -331,7 +331,7 @@ void lindexCommand(client *c) {
addReplyBulk
(
c
,
value
);
decrRefCount
(
value
);
}
else
{
addReply
(
c
,
shared
.
nullbulk
);
addReply
Null
(
c
);
}
}
else
{
serverPanic
(
"Unknown list encoding"
);
...
...
@@ -365,12 +365,12 @@ void lsetCommand(client *c) {
}
void
popGenericCommand
(
client
*
c
,
int
where
)
{
robj
*
o
=
lookupKeyWriteOrReply
(
c
,
c
->
argv
[
1
],
shared
.
null
bulk
);
robj
*
o
=
lookupKeyWriteOrReply
(
c
,
c
->
argv
[
1
],
shared
.
null
[
c
->
resp
]
);
if
(
o
==
NULL
||
checkType
(
c
,
o
,
OBJ_LIST
))
return
;
robj
*
value
=
listTypePop
(
o
,
where
);
if
(
value
==
NULL
)
{
addReply
(
c
,
shared
.
nullbulk
);
addReply
Null
(
c
);
}
else
{
char
*
event
=
(
where
==
LIST_HEAD
)
?
"lpop"
:
"rpop"
;
...
...
@@ -402,7 +402,7 @@ void lrangeCommand(client *c) {
if
((
getLongFromObjectOrReply
(
c
,
c
->
argv
[
2
],
&
start
,
NULL
)
!=
C_OK
)
||
(
getLongFromObjectOrReply
(
c
,
c
->
argv
[
3
],
&
end
,
NULL
)
!=
C_OK
))
return
;
if
((
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
emptymultibulk
))
==
NULL
if
((
o
=
lookupKeyReadOrReply
(
c
,
c
->
argv
[
1
],
shared
.
null
[
c
->
resp
]
))
==
NULL
||
checkType
(
c
,
o
,
OBJ_LIST
))
return
;
llen
=
listTypeLength
(
o
);
...
...
@@ -414,14 +414,14 @@ void lrangeCommand(client *c) {
/* Invariant: start >= 0, so this test will be true when end < 0.
* The range is empty when start > end or start >= length. */
if
(
start
>
end
||
start
>=
llen
)
{
addReply
(
c
,
shared
.
emptymultibulk
);
addReply
Null
(
c
);
return
;
}
if
(
end
>=
llen
)
end
=
llen
-
1
;
rangelen
=
(
end
-
start
)
+
1
;
/* Return the result in form of a multi-bulk reply */
addReply
MultiBulk
Len
(
c
,
rangelen
);
addReply
Array
Len
(
c
,
rangelen
);
if
(
o
->
encoding
==
OBJ_ENCODING_QUICKLIST
)
{
listTypeIterator
*
iter
=
listTypeInitIterator
(
o
,
start
,
LIST_TAIL
);
...
...
@@ -564,13 +564,13 @@ void rpoplpushHandlePush(client *c, robj *dstkey, robj *dstobj, robj *value) {
void
rpoplpushCommand
(
client
*
c
)
{
robj
*
sobj
,
*
value
;
if
((
sobj
=
lookupKeyWriteOrReply
(
c
,
c
->
argv
[
1
],
shared
.
null
bulk
))
==
NULL
||
checkType
(
c
,
sobj
,
OBJ_LIST
))
return
;
if
((
sobj
=
lookupKeyWriteOrReply
(
c
,
c
->
argv
[
1
],
shared
.
null
[
c
->
resp
]))
==
NULL
||
checkType
(
c
,
sobj
,
OBJ_LIST
))
return
;
if
(
listTypeLength
(
sobj
)
==
0
)
{
/* This may only happen after loading very old RDB files. Recent
* versions of Redis delete keys of empty lists. */
addReply
(
c
,
shared
.
nullbulk
);
addReply
Null
(
c
);
}
else
{
robj
*
dobj
=
lookupKeyWrite
(
c
->
db
,
c
->
argv
[
2
]);
robj
*
touchedkey
=
c
->
argv
[
1
];
...
...
@@ -639,7 +639,7 @@ int serveClientBlockedOnList(client *receiver, robj *key, robj *dstkey, redisDb
db
->
id
,
argv
,
2
,
PROPAGATE_AOF
|
PROPAGATE_REPL
);
/* BRPOP/BLPOP */
addReply
MultiBulk
Len
(
receiver
,
2
);
addReply
Array
Len
(
receiver
,
2
);
addReplyBulk
(
receiver
,
key
);
addReplyBulk
(
receiver
,
value
);
...
...
@@ -704,7 +704,7 @@ void blockingPopGenericCommand(client *c, int where) {
robj
*
value
=
listTypePop
(
o
,
where
);
serverAssert
(
value
!=
NULL
);
addReply
MultiBulk
Len
(
c
,
2
);
addReply
Array
Len
(
c
,
2
);
addReplyBulk
(
c
,
c
->
argv
[
j
]);
addReplyBulk
(
c
,
value
);
decrRefCount
(
value
);
...
...
@@ -731,7 +731,7 @@ void blockingPopGenericCommand(client *c, int where) {
/* If we are inside a MULTI/EXEC and the list is empty the only thing
* we can do is treating it as a timeout (even with timeout 0). */
if
(
c
->
flags
&
CLIENT_MULTI
)
{
addReply
(
c
,
shared
.
nullmultibulk
);
addReply
NullArray
(
c
);
return
;
}
...
...
@@ -759,7 +759,7 @@ void brpoplpushCommand(client *c) {
if
(
c
->
flags
&
CLIENT_MULTI
)
{
/* Blocking against an empty list in a multi state
* returns immediately. */
addReply
(
c
,
shared
.
nullbulk
);
addReply
Null
(
c
);
}
else
{
/* The list is empty and the client blocks. */
blockForKeys
(
c
,
BLOCKED_LIST
,
c
->
argv
+
1
,
1
,
timeout
,
c
->
argv
[
2
],
NULL
);
...
...
src/t_set.c
View file @
adfaf548
This diff is collapsed.
Click to expand it.
src/t_stream.c
View file @
adfaf548
This diff is collapsed.
Click to expand it.
src/t_string.c
View file @
adfaf548
This diff is collapsed.
Click to expand it.
src/t_zset.c
View file @
adfaf548
This diff is collapsed.
Click to expand it.
tests/integration/replication.tcl
View file @
adfaf548
...
...
@@ -275,7 +275,6 @@ start_server {tags {"repl"}} {
start_server
{}
{
test
"Master stream is correctly processed while the replica has a script in -BUSY state"
{
set slave
[
srv 0 client
]
puts
[
srv 0 port
]
$slave config set lua-time-limit 500
$slave slaveof $master_host $master_port
...
...
tests/unit/auth.tcl
View file @
adfaf548
...
...
@@ -2,14 +2,14 @@ start_server {tags {"auth"}} {
test
{
AUTH fails if there is no password configured server side
}
{
catch
{
r auth foo
}
err
set _ $err
}
{
ERR*
no
password*
}
}
{
ERR*
any
password*
}
}
start_server
{
tags
{
"auth"
}
overrides
{
requirepass foobar
}}
{
test
{
AUTH fails when a wrong password is given
}
{
catch
{
r auth wrong!
}
err
set _ $err
}
{
ERR*invalid password
}
}
{
WRONGPASS*
}
test
{
Arbitrary command gives an error when AUTH is required
}
{
catch
{
r set foo bar
}
err
...
...
tests/unit/dump.tcl
View file @
adfaf548
...
...
@@ -362,7 +362,7 @@ start_server {tags {"dump"}} {
r -1 lpush list a b c d
$second config set requirepass foobar2
catch
{
r -1 migrate $second_host $second_port list 9 5000 AUTH foobar
}
err
assert_match
{
*
invalid password
*
}
$err
assert_match
{
*
WRONGPASS
*
}
$err
}
}
}
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