Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
hanoi2005
redis
提交
6e469882
R
redis
项目概览
hanoi2005
/
redis
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
redis
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
6e469882
编写于
12月 27, 2009
作者:
A
antirez
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
MULTI/EXEC first implementation
上级
322fc7d8
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
117 addition
and
12 deletion
+117
-12
redis.c
redis.c
+117
-12
未找到文件。
redis.c
浏览文件 @
6e469882
...
...
@@ -157,6 +157,7 @@
#define REDIS_SLAVE 2
/* This client is a slave server */
#define REDIS_MASTER 4
/* This client is a master server */
#define REDIS_MONITOR 8
/* This client is a slave monitor, see MONITOR */
#define REDIS_MULTI 16
/* This client is in a MULTI context */
/* Slave replication state - slave side */
#define REDIS_REPL_NONE 0
/* No active replication */
...
...
@@ -230,6 +231,18 @@ typedef struct redisDb {
int
id
;
}
redisDb
;
/* Client MULTI/EXEC state */
typedef
struct
multiCmd
{
robj
**
argv
;
int
argc
;
struct
redisCommand
*
cmd
;
}
multiCmd
;
typedef
struct
multiState
{
multiCmd
*
commands
;
/* Array of MULTI commands */
int
count
;
/* Total number of MULTI commands */
}
multiState
;
/* With multiplexing we need to take per-clinet state.
* Clients are taken in a liked list. */
typedef
struct
redisClient
{
...
...
@@ -245,12 +258,14 @@ typedef struct redisClient {
int
sentlen
;
time_t
lastinteraction
;
/* time of the last interaction, used for timeout */
int
flags
;
/* REDIS_CLOSE | REDIS_SLAVE | REDIS_MONITOR */
/* REDIS_MULTI */
int
slaveseldb
;
/* slave selected db, if this client is a slave */
int
authenticated
;
/* when requirepass is non-NULL */
int
replstate
;
/* replication state if this is a slave */
int
repldbfd
;
/* replication DB file descriptor */
long
repldboff
;
/* replication DB file offset */
long
repldboff
;
/* replication DB file offset */
off_t
repldbsize
;
/* replication DB file size */
multiState
mstate
;
/* MULTI/EXEC state */
}
redisClient
;
struct
saveparam
{
...
...
@@ -368,7 +383,7 @@ typedef struct zset {
struct
sharedObjectsStruct
{
robj
*
crlf
,
*
ok
,
*
err
,
*
emptybulk
,
*
czero
,
*
cone
,
*
pong
,
*
space
,
*
colon
,
*
nullbulk
,
*
nullmultibulk
,
*
colon
,
*
nullbulk
,
*
nullmultibulk
,
*
queued
,
*
emptymultibulk
,
*
wrongtypeerr
,
*
nokeyerr
,
*
syntaxerr
,
*
sameobjecterr
,
*
outofrangeerr
,
*
plus
,
*
select0
,
*
select1
,
*
select2
,
*
select3
,
*
select4
,
...
...
@@ -419,6 +434,9 @@ static zskiplist *zslCreate(void);
static
void
zslFree
(
zskiplist
*
zsl
);
static
void
zslInsert
(
zskiplist
*
zsl
,
double
score
,
robj
*
obj
);
static
void
sendReplyToClientWritev
(
aeEventLoop
*
el
,
int
fd
,
void
*
privdata
,
int
mask
);
static
void
initClientMultiState
(
redisClient
*
c
);
static
void
freeClientMultiState
(
redisClient
*
c
);
static
void
queueMultiCommand
(
redisClient
*
c
,
struct
redisCommand
*
cmd
);
static
void
authCommand
(
redisClient
*
c
);
static
void
pingCommand
(
redisClient
*
c
);
...
...
@@ -493,6 +511,8 @@ static void zcardCommand(redisClient *c);
static
void
zremCommand
(
redisClient
*
c
);
static
void
zscoreCommand
(
redisClient
*
c
);
static
void
zremrangebyscoreCommand
(
redisClient
*
c
);
static
void
multiCommand
(
redisClient
*
c
);
static
void
execCommand
(
redisClient
*
c
);
/*================================= Globals ================================= */
...
...
@@ -564,6 +584,8 @@ static struct redisCommand cmdTable[] = {
{
"shutdown"
,
shutdownCommand
,
1
,
REDIS_CMD_INLINE
},
{
"lastsave"
,
lastsaveCommand
,
1
,
REDIS_CMD_INLINE
},
{
"type"
,
typeCommand
,
2
,
REDIS_CMD_INLINE
},
{
"multi"
,
multiCommand
,
1
,
REDIS_CMD_INLINE
},
{
"exec"
,
execCommand
,
1
,
REDIS_CMD_INLINE
},
{
"sync"
,
syncCommand
,
1
,
REDIS_CMD_INLINE
},
{
"flushdb"
,
flushdbCommand
,
1
,
REDIS_CMD_INLINE
},
{
"flushall"
,
flushallCommand
,
1
,
REDIS_CMD_INLINE
},
...
...
@@ -1083,6 +1105,7 @@ static void createSharedObjects(void) {
shared
.
nullmultibulk
=
createObject
(
REDIS_STRING
,
sdsnew
(
"*-1
\r\n
"
));
shared
.
emptymultibulk
=
createObject
(
REDIS_STRING
,
sdsnew
(
"*0
\r\n
"
));
shared
.
pong
=
createObject
(
REDIS_STRING
,
sdsnew
(
"+PONG
\r\n
"
));
shared
.
queued
=
createObject
(
REDIS_STRING
,
sdsnew
(
"+QUEUED
\r\n
"
));
shared
.
wrongtypeerr
=
createObject
(
REDIS_STRING
,
sdsnew
(
"-ERR Operation against a key holding the wrong kind of value
\r\n
"
));
shared
.
nokeyerr
=
createObject
(
REDIS_STRING
,
sdsnew
(
...
...
@@ -1432,6 +1455,7 @@ static void freeClient(redisClient *c) {
}
zfree
(
c
->
argv
);
zfree
(
c
->
mbargv
);
freeClientMultiState
(
c
);
zfree
(
c
);
}
...
...
@@ -1622,6 +1646,21 @@ static void resetClient(redisClient *c) {
c
->
multibulk
=
0
;
}
/* Call() is the core of Redis execution of a command */
static
void
call
(
redisClient
*
c
,
struct
redisCommand
*
cmd
)
{
long
long
dirty
;
dirty
=
server
.
dirty
;
cmd
->
proc
(
c
);
if
(
server
.
appendonly
&&
server
.
dirty
-
dirty
)
feedAppendOnlyFile
(
cmd
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
if
(
server
.
dirty
-
dirty
&&
listLength
(
server
.
slaves
))
replicationFeedSlaves
(
server
.
slaves
,
cmd
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
if
(
listLength
(
server
.
monitors
))
replicationFeedSlaves
(
server
.
monitors
,
cmd
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
server
.
stat_numcommands
++
;
}
/* If this function gets called we already read a whole
* command, argments are in the client argv/argc fields.
* processCommand() execute the command or prepare the
...
...
@@ -1632,7 +1671,6 @@ static void resetClient(redisClient *c) {
* if 0 is returned the client was destroied (i.e. after QUIT). */
static
int
processCommand
(
redisClient
*
c
)
{
struct
redisCommand
*
cmd
;
long
long
dirty
;
/* Free some memory if needed (maxmemory setting) */
if
(
server
.
maxmemory
)
freeMemoryIfNeeded
();
...
...
@@ -1773,15 +1811,12 @@ static int processCommand(redisClient *c) {
}
/* Exec the command */
dirty
=
server
.
dirty
;
cmd
->
proc
(
c
);
if
(
server
.
appendonly
&&
server
.
dirty
-
dirty
)
feedAppendOnlyFile
(
cmd
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
if
(
server
.
dirty
-
dirty
&&
listLength
(
server
.
slaves
))
replicationFeedSlaves
(
server
.
slaves
,
cmd
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
if
(
listLength
(
server
.
monitors
))
replicationFeedSlaves
(
server
.
monitors
,
cmd
,
c
->
db
->
id
,
c
->
argv
,
c
->
argc
);
server
.
stat_numcommands
++
;
if
(
c
->
flags
&
REDIS_MULTI
&&
cmd
->
proc
!=
execCommand
)
{
queueMultiCommand
(
c
,
cmd
);
addReply
(
c
,
shared
.
queued
);
}
else
{
call
(
c
,
cmd
);
}
/* Prepare the client for the next command */
if
(
c
->
flags
&
REDIS_CLOSE
)
{
...
...
@@ -2007,6 +2042,7 @@ static redisClient *createClient(int fd) {
return
NULL
;
}
listAddNodeTail
(
server
.
clients
,
c
);
initClientMultiState
(
c
);
return
c
;
}
...
...
@@ -5287,6 +5323,75 @@ static void ttlCommand(redisClient *c) {
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
":%d
\r\n
"
,
ttl
));
}
/* ================================ MULTI/EXEC ============================== */
/* Client state initialization for MULTI/EXEC */
static
void
initClientMultiState
(
redisClient
*
c
)
{
c
->
mstate
.
commands
=
NULL
;
c
->
mstate
.
count
=
0
;
}
/* Release all the resources associated with MULTI/EXEC state */
static
void
freeClientMultiState
(
redisClient
*
c
)
{
int
j
;
for
(
j
=
0
;
j
<
c
->
mstate
.
count
;
j
++
)
{
int
i
;
multiCmd
*
mc
=
c
->
mstate
.
commands
+
j
;
for
(
i
=
0
;
i
<
mc
->
argc
;
i
++
)
decrRefCount
(
mc
->
argv
[
i
]);
zfree
(
mc
->
argv
);
}
zfree
(
c
->
mstate
.
commands
);
}
/* Add a new command into the MULTI commands queue */
static
void
queueMultiCommand
(
redisClient
*
c
,
struct
redisCommand
*
cmd
)
{
multiCmd
*
mc
;
int
j
;
c
->
mstate
.
commands
=
zrealloc
(
c
->
mstate
.
commands
,
sizeof
(
multiCmd
)
*
(
c
->
mstate
.
count
+
1
));
mc
=
c
->
mstate
.
commands
+
c
->
mstate
.
count
;
mc
->
cmd
=
cmd
;
mc
->
argc
=
c
->
argc
;
mc
->
argv
=
zmalloc
(
sizeof
(
robj
*
)
*
c
->
argc
);
memcpy
(
mc
->
argv
,
c
->
argv
,
sizeof
(
robj
*
)
*
c
->
argc
);
for
(
j
=
0
;
j
<
c
->
argc
;
j
++
)
incrRefCount
(
mc
->
argv
[
j
]);
c
->
mstate
.
count
++
;
}
static
void
multiCommand
(
redisClient
*
c
)
{
c
->
flags
|=
REDIS_MULTI
;
}
static
void
execCommand
(
redisClient
*
c
)
{
int
j
;
robj
**
orig_argv
;
int
orig_argc
;
if
(
!
(
c
->
flags
&
REDIS_MULTI
))
{
addReplySds
(
c
,
sdsnew
(
"-ERR EXEC without MULTI
\r\n
"
));
return
;
}
orig_argv
=
c
->
argv
;
orig_argc
=
c
->
argc
;
addReplySds
(
c
,
sdscatprintf
(
sdsempty
(),
"*%d
\r\n
"
,
c
->
mstate
.
count
));
for
(
j
=
0
;
j
<
c
->
mstate
.
count
;
j
++
)
{
c
->
argc
=
c
->
mstate
.
commands
[
j
].
argc
;
c
->
argv
=
c
->
mstate
.
commands
[
j
].
argv
;
call
(
c
,
c
->
mstate
.
commands
[
j
].
cmd
);
}
c
->
argv
=
orig_argv
;
c
->
argc
=
orig_argc
;
freeClientMultiState
(
c
);
initClientMultiState
(
c
);
c
->
flags
&=
(
~
REDIS_MULTI
);
}
/* =============================== Replication ============================= */
static
int
syncWrite
(
int
fd
,
char
*
ptr
,
ssize_t
size
,
int
timeout
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录