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
9682a58f
Commit
9682a58f
authored
May 13, 2010
by
antirez
Browse files
conflicts resolved
parents
32a66513
9376e434
Changes
3
Show whitespace changes
Inline
Side-by-side
redis-cli.c
View file @
9682a58f
...
@@ -112,8 +112,8 @@ static struct redisCommand cmdTable[] = {
...
@@ -112,8 +112,8 @@ static struct redisCommand cmdTable[] = {
{
"zincrby"
,
4
,
CMDFLAG_NONE
},
{
"zincrby"
,
4
,
CMDFLAG_NONE
},
{
"zrem"
,
3
,
CMDFLAG_NONE
},
{
"zrem"
,
3
,
CMDFLAG_NONE
},
{
"zremrangebyscore"
,
4
,
CMDFLAG_NONE
},
{
"zremrangebyscore"
,
4
,
CMDFLAG_NONE
},
{
"z
merge
"
,
-
3
,
CMDFLAG_NONE
},
{
"z
union
"
,
-
4
,
CMDFLAG_NONE
},
{
"z
mergeweighed
"
,
-
4
,
CMDFLAG_NONE
},
{
"z
inter
"
,
-
4
,
CMDFLAG_NONE
},
{
"zrange"
,
-
4
,
CMDFLAG_NONE
},
{
"zrange"
,
-
4
,
CMDFLAG_NONE
},
{
"zrank"
,
3
,
CMDFLAG_NONE
},
{
"zrank"
,
3
,
CMDFLAG_NONE
},
{
"zrevrank"
,
3
,
CMDFLAG_NONE
},
{
"zrevrank"
,
3
,
CMDFLAG_NONE
},
...
...
redis.c
View file @
9682a58f
...
@@ -451,6 +451,7 @@ typedef struct pubsubPattern {
...
@@ -451,6 +451,7 @@ typedef struct pubsubPattern {
}
pubsubPattern
;
}
pubsubPattern
;
typedef
void
redisCommandProc
(
redisClient
*
c
);
typedef
void
redisCommandProc
(
redisClient
*
c
);
typedef
void
redisVmPreloadProc
(
redisClient
*
c
,
struct
redisCommand
*
cmd
,
int
argc
,
robj
**
argv
);
struct
redisCommand
{
struct
redisCommand
{
char
*
name
;
char
*
name
;
redisCommandProc
*
proc
;
redisCommandProc
*
proc
;
...
@@ -459,7 +460,7 @@ struct redisCommand {
...
@@ -459,7 +460,7 @@ struct redisCommand {
/* Use a function to determine which keys need to be loaded
/* Use a function to determine which keys need to be loaded
* in the background prior to executing this command. Takes precedence
* in the background prior to executing this command. Takes precedence
* over vm_firstkey and others, ignored when NULL */
* over vm_firstkey and others, ignored when NULL */
redis
Comman
dProc
*
vm_preload_proc
;
redis
VmPreloa
dProc
*
vm_preload_proc
;
/* What keys should be loaded in background when calling this command? */
/* What keys should be loaded in background when calling this command? */
int
vm_firstkey
;
/* The first argument that's a key (0 = no keys) */
int
vm_firstkey
;
/* The first argument that's a key (0 = no keys) */
int
vm_lastkey
;
/* THe last argument that's a key */
int
vm_lastkey
;
/* THe last argument that's a key */
...
@@ -609,8 +610,9 @@ static robj *vmReadObjectFromSwap(off_t page, int type);
...
@@ -609,8 +610,9 @@ static robj *vmReadObjectFromSwap(off_t page, int type);
static
void
waitEmptyIOJobsQueue
(
void
);
static
void
waitEmptyIOJobsQueue
(
void
);
static
void
vmReopenSwapFile
(
void
);
static
void
vmReopenSwapFile
(
void
);
static
int
vmFreePage
(
off_t
page
);
static
int
vmFreePage
(
off_t
page
);
static
void
zunionInterBlockClientOnSwappedKeys
(
redisClient
*
c
);
static
void
zunionInterBlockClientOnSwappedKeys
(
redisClient
*
c
,
struct
redisCommand
*
cmd
,
int
argc
,
robj
**
argv
);
static
int
blockClientOnSwappedKeys
(
struct
redisCommand
*
cmd
,
redisClient
*
c
);
static
void
execBlockClientOnSwappedKeys
(
redisClient
*
c
,
struct
redisCommand
*
cmd
,
int
argc
,
robj
**
argv
);
static
int
blockClientOnSwappedKeys
(
redisClient
*
c
,
struct
redisCommand
*
cmd
);
static
int
dontWaitForSwappedKey
(
redisClient
*
c
,
robj
*
key
);
static
int
dontWaitForSwappedKey
(
redisClient
*
c
,
robj
*
key
);
static
void
handleClientsBlockedOnSwappedKey
(
redisDb
*
db
,
robj
*
key
);
static
void
handleClientsBlockedOnSwappedKey
(
redisDb
*
db
,
robj
*
key
);
static
void
readQueryFromClient
(
aeEventLoop
*
el
,
int
fd
,
void
*
privdata
,
int
mask
);
static
void
readQueryFromClient
(
aeEventLoop
*
el
,
int
fd
,
void
*
privdata
,
int
mask
);
...
@@ -828,7 +830,7 @@ static struct redisCommand cmdTable[] = {
...
@@ -828,7 +830,7 @@ static struct redisCommand cmdTable[] = {
{
"lastsave"
,
lastsaveCommand
,
1
,
REDIS_CMD_INLINE
,
NULL
,
0
,
0
,
0
},
{
"lastsave"
,
lastsaveCommand
,
1
,
REDIS_CMD_INLINE
,
NULL
,
0
,
0
,
0
},
{
"type"
,
typeCommand
,
2
,
REDIS_CMD_INLINE
,
NULL
,
1
,
1
,
1
},
{
"type"
,
typeCommand
,
2
,
REDIS_CMD_INLINE
,
NULL
,
1
,
1
,
1
},
{
"multi"
,
multiCommand
,
1
,
REDIS_CMD_INLINE
,
NULL
,
0
,
0
,
0
},
{
"multi"
,
multiCommand
,
1
,
REDIS_CMD_INLINE
,
NULL
,
0
,
0
,
0
},
{
"exec"
,
execCommand
,
1
,
REDIS_CMD_INLINE
|
REDIS_CMD_DENYOOM
,
NULL
,
0
,
0
,
0
},
{
"exec"
,
execCommand
,
1
,
REDIS_CMD_INLINE
|
REDIS_CMD_DENYOOM
,
execBlockClientOnSwappedKeys
,
0
,
0
,
0
},
{
"discard"
,
discardCommand
,
1
,
REDIS_CMD_INLINE
,
NULL
,
0
,
0
,
0
},
{
"discard"
,
discardCommand
,
1
,
REDIS_CMD_INLINE
,
NULL
,
0
,
0
,
0
},
{
"sync"
,
syncCommand
,
1
,
REDIS_CMD_INLINE
,
NULL
,
0
,
0
,
0
},
{
"sync"
,
syncCommand
,
1
,
REDIS_CMD_INLINE
,
NULL
,
0
,
0
,
0
},
{
"flushdb"
,
flushdbCommand
,
1
,
REDIS_CMD_INLINE
,
NULL
,
0
,
0
,
0
},
{
"flushdb"
,
flushdbCommand
,
1
,
REDIS_CMD_INLINE
,
NULL
,
0
,
0
,
0
},
...
@@ -1913,6 +1915,9 @@ static void loadServerConfig(char *filename) {
...
@@ -1913,6 +1915,9 @@ static void loadServerConfig(char *filename) {
if
((
server
.
appendonly
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
if
((
server
.
appendonly
=
yesnotoi
(
argv
[
1
]))
==
-
1
)
{
err
=
"argument must be 'yes' or 'no'"
;
goto
loaderr
;
err
=
"argument must be 'yes' or 'no'"
;
goto
loaderr
;
}
}
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"appendfilename"
)
&&
argc
==
2
)
{
zfree
(
server
.
appendfilename
);
server
.
appendfilename
=
zstrdup
(
argv
[
1
]);
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"appendfsync"
)
&&
argc
==
2
)
{
}
else
if
(
!
strcasecmp
(
argv
[
0
],
"appendfsync"
)
&&
argc
==
2
)
{
if
(
!
strcasecmp
(
argv
[
1
],
"no"
))
{
if
(
!
strcasecmp
(
argv
[
1
],
"no"
))
{
server
.
appendfsync
=
APPENDFSYNC_NO
;
server
.
appendfsync
=
APPENDFSYNC_NO
;
...
@@ -2418,7 +2423,7 @@ static int processCommand(redisClient *c) {
...
@@ -2418,7 +2423,7 @@ static int processCommand(redisClient *c) {
addReply
(
c
,
shared
.
queued
);
addReply
(
c
,
shared
.
queued
);
}
else
{
}
else
{
if
(
server
.
vm_enabled
&&
server
.
vm_max_threads
>
0
&&
if
(
server
.
vm_enabled
&&
server
.
vm_max_threads
>
0
&&
blockClientOnSwappedKeys
(
c
md
,
c
))
return
1
;
blockClientOnSwappedKeys
(
c
,
c
md
))
return
1
;
call
(
c
,
cmd
);
call
(
c
,
cmd
);
}
}
...
@@ -4463,7 +4468,12 @@ static void delCommand(redisClient *c) {
...
@@ -4463,7 +4468,12 @@ static void delCommand(redisClient *c) {
}
}
static
void
existsCommand
(
redisClient
*
c
)
{
static
void
existsCommand
(
redisClient
*
c
)
{
addReply
(
c
,
lookupKeyRead
(
c
->
db
,
c
->
argv
[
1
])
?
shared
.
cone
:
shared
.
czero
);
expireIfNeeded
(
c
->
db
,
c
->
argv
[
1
]);
if
(
dictFind
(
c
->
db
->
dict
,
c
->
argv
[
1
]))
{
addReply
(
c
,
shared
.
cone
);
}
else
{
addReply
(
c
,
shared
.
czero
);
}
}
}
static
void
selectCommand
(
redisClient
*
c
)
{
static
void
selectCommand
(
redisClient
*
c
)
{
...
@@ -8178,9 +8188,41 @@ static void flushAppendOnlyFile(void) {
...
@@ -8178,9 +8188,41 @@ static void flushAppendOnlyFile(void) {
}
}
}
}
static
sds
catAppendOnlyGenericCommand
(
sds
buf
,
int
argc
,
robj
**
argv
)
{
int
j
;
buf
=
sdscatprintf
(
buf
,
"*%d
\r\n
"
,
argc
);
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
robj
*
o
=
getDecodedObject
(
argv
[
j
]);
buf
=
sdscatprintf
(
buf
,
"$%lu
\r\n
"
,(
unsigned
long
)
sdslen
(
o
->
ptr
));
buf
=
sdscatlen
(
buf
,
o
->
ptr
,
sdslen
(
o
->
ptr
));
buf
=
sdscatlen
(
buf
,
"
\r\n
"
,
2
);
decrRefCount
(
o
);
}
return
buf
;
}
static
sds
catAppendOnlyExpireAtCommand
(
sds
buf
,
robj
*
key
,
robj
*
seconds
)
{
int
argc
=
3
;
long
when
;
robj
*
argv
[
3
];
/* Make sure we can use strtol */
seconds
=
getDecodedObject
(
seconds
);
when
=
time
(
NULL
)
+
strtol
(
seconds
->
ptr
,
NULL
,
10
);
decrRefCount
(
seconds
);
argv
[
0
]
=
createStringObject
(
"EXPIREAT"
,
8
);
argv
[
1
]
=
key
;
argv
[
2
]
=
createObject
(
REDIS_STRING
,
sdscatprintf
(
sdsempty
(),
"%ld"
,
when
));
buf
=
catAppendOnlyGenericCommand
(
buf
,
argc
,
argv
);
decrRefCount
(
argv
[
0
]);
decrRefCount
(
argv
[
2
]);
return
buf
;
}
static
void
feedAppendOnlyFile
(
struct
redisCommand
*
cmd
,
int
dictid
,
robj
**
argv
,
int
argc
)
{
static
void
feedAppendOnlyFile
(
struct
redisCommand
*
cmd
,
int
dictid
,
robj
**
argv
,
int
argc
)
{
sds
buf
=
sdsempty
();
sds
buf
=
sdsempty
();
int
j
;
robj
*
tmpargv
[
3
];
robj
*
tmpargv
[
3
];
/* The DB this command was targetting is not the same as the last command
/* The DB this command was targetting is not the same as the last command
...
@@ -8194,36 +8236,19 @@ static void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv
...
@@ -8194,36 +8236,19 @@ static void feedAppendOnlyFile(struct redisCommand *cmd, int dictid, robj **argv
server
.
appendseldb
=
dictid
;
server
.
appendseldb
=
dictid
;
}
}
/* "Fix" the argv vector if the command is EXPIRE. We want to translate
* EXPIREs into EXPIREATs calls */
if
(
cmd
->
proc
==
expireCommand
)
{
if
(
cmd
->
proc
==
expireCommand
)
{
long
when
;
/* Translate EXPIRE into EXPIREAT */
buf
=
catAppendOnlyExpireAtCommand
(
buf
,
argv
[
1
],
argv
[
2
]);
tmpargv
[
0
]
=
createStringObject
(
"EXPIREAT"
,
8
);
}
else
if
(
cmd
->
proc
==
setexCommand
)
{
/* Translate SETEX to SET and EXPIREAT */
tmpargv
[
0
]
=
createStringObject
(
"SET"
,
3
);
tmpargv
[
1
]
=
argv
[
1
];
tmpargv
[
1
]
=
argv
[
1
];
incrRefCount
(
argv
[
1
]);
tmpargv
[
2
]
=
argv
[
3
];
when
=
time
(
NULL
)
+
strtol
(
argv
[
2
]
->
ptr
,
NULL
,
10
);
buf
=
catAppendOnlyGenericCommand
(
buf
,
3
,
tmpargv
);
tmpargv
[
2
]
=
createObject
(
REDIS_STRING
,
decrRefCount
(
tmpargv
[
0
]);
sdscatprintf
(
sdsempty
(),
"%ld"
,
when
));
buf
=
catAppendOnlyExpireAtCommand
(
buf
,
argv
[
1
],
argv
[
2
]);
argv
=
tmpargv
;
}
else
{
}
buf
=
catAppendOnlyGenericCommand
(
buf
,
argc
,
argv
);
/* Append the actual command */
buf
=
sdscatprintf
(
buf
,
"*%d
\r\n
"
,
argc
);
for
(
j
=
0
;
j
<
argc
;
j
++
)
{
robj
*
o
=
argv
[
j
];
o
=
getDecodedObject
(
o
);
buf
=
sdscatprintf
(
buf
,
"$%lu
\r\n
"
,(
unsigned
long
)
sdslen
(
o
->
ptr
));
buf
=
sdscatlen
(
buf
,
o
->
ptr
,
sdslen
(
o
->
ptr
));
buf
=
sdscatlen
(
buf
,
"
\r\n
"
,
2
);
decrRefCount
(
o
);
}
/* Free the objects from the modified argv for EXPIREAT */
if
(
cmd
->
proc
==
expireCommand
)
{
for
(
j
=
0
;
j
<
3
;
j
++
)
decrRefCount
(
argv
[
j
]);
}
}
/* Append to the AOF buffer. This will be flushed on disk just before
/* Append to the AOF buffer. This will be flushed on disk just before
...
@@ -9660,12 +9685,56 @@ static int waitForSwappedKey(redisClient *c, robj *key) {
...
@@ -9660,12 +9685,56 @@ static int waitForSwappedKey(redisClient *c, robj *key) {
return
1
;
return
1
;
}
}
/* Preload keys needed for the ZUNION and ZINTER commands. */
/* Preload keys for any command with first, last and step values for
static
void
zunionInterBlockClientOnSwappedKeys
(
redisClient
*
c
)
{
* the command keys prototype, as defined in the command table. */
static
void
waitForMultipleSwappedKeys
(
redisClient
*
c
,
struct
redisCommand
*
cmd
,
int
argc
,
robj
**
argv
)
{
int
j
,
last
;
if
(
cmd
->
vm_firstkey
==
0
)
return
;
last
=
cmd
->
vm_lastkey
;
if
(
last
<
0
)
last
=
argc
+
last
;
for
(
j
=
cmd
->
vm_firstkey
;
j
<=
last
;
j
+=
cmd
->
vm_keystep
)
{
redisAssert
(
j
<
argc
);
waitForSwappedKey
(
c
,
argv
[
j
]);
}
}
/* Preload keys needed for the ZUNION and ZINTER commands.
* Note that the number of keys to preload is user-defined, so we need to
* apply a sanity check against argc. */
static
void
zunionInterBlockClientOnSwappedKeys
(
redisClient
*
c
,
struct
redisCommand
*
cmd
,
int
argc
,
robj
**
argv
)
{
int
i
,
num
;
int
i
,
num
;
num
=
atoi
(
c
->
argv
[
2
]
->
ptr
);
REDIS_NOTUSED
(
cmd
);
num
=
atoi
(
argv
[
2
]
->
ptr
);
if
(
num
>
(
argc
-
3
))
return
;
for
(
i
=
0
;
i
<
num
;
i
++
)
{
for
(
i
=
0
;
i
<
num
;
i
++
)
{
waitForSwappedKey
(
c
,
c
->
argv
[
3
+
i
]);
waitForSwappedKey
(
c
,
argv
[
3
+
i
]);
}
}
/* Preload keys needed to execute the entire MULTI/EXEC block.
*
* This function is called by blockClientOnSwappedKeys when EXEC is issued,
* and will block the client when any command requires a swapped out value. */
static
void
execBlockClientOnSwappedKeys
(
redisClient
*
c
,
struct
redisCommand
*
cmd
,
int
argc
,
robj
**
argv
)
{
int
i
,
margc
;
struct
redisCommand
*
mcmd
;
robj
**
margv
;
REDIS_NOTUSED
(
cmd
);
REDIS_NOTUSED
(
argc
);
REDIS_NOTUSED
(
argv
);
if
(
!
(
c
->
flags
&
REDIS_MULTI
))
return
;
for
(
i
=
0
;
i
<
c
->
mstate
.
count
;
i
++
)
{
mcmd
=
c
->
mstate
.
commands
[
i
].
cmd
;
margc
=
c
->
mstate
.
commands
[
i
].
argc
;
margv
=
c
->
mstate
.
commands
[
i
].
argv
;
if
(
mcmd
->
vm_preload_proc
!=
NULL
)
{
mcmd
->
vm_preload_proc
(
c
,
mcmd
,
margc
,
margv
);
}
else
{
waitForMultipleSwappedKeys
(
c
,
mcmd
,
margc
,
margv
);
}
}
}
}
}
...
@@ -9679,17 +9748,11 @@ static void zunionInterBlockClientOnSwappedKeys(redisClient *c) {
...
@@ -9679,17 +9748,11 @@ static void zunionInterBlockClientOnSwappedKeys(redisClient *c) {
*
*
* Return 1 if the client is marked as blocked, 0 if the client can
* Return 1 if the client is marked as blocked, 0 if the client can
* continue as the keys it is going to access appear to be in memory. */
* continue as the keys it is going to access appear to be in memory. */
static
int
blockClientOnSwappedKeys
(
struct
redisCommand
*
cmd
,
redisClient
*
c
)
{
static
int
blockClientOnSwappedKeys
(
redisClient
*
c
,
struct
redisCommand
*
cmd
)
{
int
j
,
last
;
if
(
cmd
->
vm_preload_proc
!=
NULL
)
{
if
(
cmd
->
vm_preload_proc
!=
NULL
)
{
cmd
->
vm_preload_proc
(
c
);
cmd
->
vm_preload_proc
(
c
,
cmd
,
c
->
argc
,
c
->
argv
);
}
else
{
}
else
{
if
(
cmd
->
vm_firstkey
==
0
)
return
0
;
waitForMultipleSwappedKeys
(
c
,
cmd
,
c
->
argc
,
c
->
argv
);
last
=
cmd
->
vm_lastkey
;
if
(
last
<
0
)
last
=
c
->
argc
+
last
;
for
(
j
=
cmd
->
vm_firstkey
;
j
<=
last
;
j
+=
cmd
->
vm_keystep
)
waitForSwappedKey
(
c
,
c
->
argv
[
j
]);
}
}
/* If the client was blocked for at least one key, mark it as blocked. */
/* If the client was blocked for at least one key, mark it as blocked. */
...
...
redis.conf
View file @
9682a58f
...
@@ -163,13 +163,14 @@ dir ./
...
@@ -163,13 +163,14 @@ dir ./
# Still if append only mode is enabled Redis will load the data from the
# Still if append only mode is enabled Redis will load the data from the
# log file at startup ignoring the dump.rdb file.
# log file at startup ignoring the dump.rdb file.
#
#
# The name of the append only file is "appendonly.aof"
#
# IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append
# IMPORTANT: Check the BGREWRITEAOF to check how to rewrite the append
# log file in background when it gets too big.
# log file in background when it gets too big.
appendonly
no
appendonly
no
# The name of the append only file (default: "appendonly.aof")
# appendfilename appendonly.aof
# The fsync() call tells the Operating System to actually write data on disk
# The fsync() call tells the Operating System to actually write data on disk
# instead to wait for more data in the output buffer. Some OS will really flush
# instead to wait for more data in the output buffer. Some OS will really flush
# data on disk, some other OS will just try to do it ASAP.
# data on disk, some other OS will just try to do it ASAP.
...
...
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