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
c7df85a4
Commit
c7df85a4
authored
Jan 13, 2010
by
antirez
Browse files
list API is now thread safe
parent
b74880b4
Changes
3
Hide whitespace changes
Inline
Side-by-side
adlist.c
View file @
c7df85a4
...
@@ -165,14 +165,14 @@ void listReleaseIterator(listIter *iter) {
...
@@ -165,14 +165,14 @@ void listReleaseIterator(listIter *iter) {
}
}
/* Create an iterator in the list private iterator structure */
/* Create an iterator in the list private iterator structure */
void
listRewind
(
list
*
list
)
{
void
listRewind
(
list
*
list
,
listIter
*
li
)
{
li
st
->
iter
.
next
=
list
->
head
;
li
->
next
=
list
->
head
;
li
st
->
iter
.
direction
=
AL_START_HEAD
;
li
->
direction
=
AL_START_HEAD
;
}
}
void
listRewindTail
(
list
*
list
)
{
void
listRewindTail
(
list
*
list
,
listIter
*
li
)
{
li
st
->
iter
.
next
=
list
->
tail
;
li
->
next
=
list
->
tail
;
li
st
->
iter
.
direction
=
AL_START_TAIL
;
li
->
direction
=
AL_START_TAIL
;
}
}
/* Return the next element of an iterator.
/* Return the next element of an iterator.
...
@@ -202,11 +202,6 @@ listNode *listNext(listIter *iter)
...
@@ -202,11 +202,6 @@ listNode *listNext(listIter *iter)
return
current
;
return
current
;
}
}
/* List Yield just call listNext() against the list private iterator */
listNode
*
listYield
(
list
*
list
)
{
return
listNext
(
&
list
->
iter
);
}
/* Duplicate the whole list. On out of memory NULL is returned.
/* Duplicate the whole list. On out of memory NULL is returned.
* On success a copy of the original list is returned.
* On success a copy of the original list is returned.
*
*
...
...
adlist.h
View file @
c7df85a4
...
@@ -51,7 +51,6 @@ typedef struct list {
...
@@ -51,7 +51,6 @@ typedef struct list {
void
(
*
free
)(
void
*
ptr
);
void
(
*
free
)(
void
*
ptr
);
int
(
*
match
)(
void
*
ptr
,
void
*
key
);
int
(
*
match
)(
void
*
ptr
,
void
*
key
);
unsigned
int
len
;
unsigned
int
len
;
listIter
iter
;
}
list
;
}
list
;
/* Functions implemented as macros */
/* Functions implemented as macros */
...
@@ -82,9 +81,8 @@ void listReleaseIterator(listIter *iter);
...
@@ -82,9 +81,8 @@ void listReleaseIterator(listIter *iter);
list
*
listDup
(
list
*
orig
);
list
*
listDup
(
list
*
orig
);
listNode
*
listSearchKey
(
list
*
list
,
void
*
key
);
listNode
*
listSearchKey
(
list
*
list
,
void
*
key
);
listNode
*
listIndex
(
list
*
list
,
int
index
);
listNode
*
listIndex
(
list
*
list
,
int
index
);
void
listRewind
(
list
*
list
);
void
listRewind
(
list
*
list
,
listIter
*
li
);
void
listRewindTail
(
list
*
list
);
void
listRewindTail
(
list
*
list
,
listIter
*
li
);
listNode
*
listYield
(
list
*
list
);
/* Directions for iterators */
/* Directions for iterators */
#define AL_START_HEAD 0
#define AL_START_HEAD 0
...
...
redis.c
View file @
c7df85a4
...
@@ -1018,9 +1018,10 @@ static void closeTimedoutClients(void) {
...
@@ -1018,9 +1018,10 @@ static void closeTimedoutClients(void) {
redisClient *c;
redisClient *c;
listNode *ln;
listNode *ln;
time_t now = time(NULL);
time_t now = time(NULL);
listIter li;
listRewind
(
server
.
clients
);
listRewind(server.clients
,&li
);
while
((
ln
=
list
Yield
(
server
.
clients
))
!=
NULL
)
{
while ((ln = list
Next(&li
)) != NULL) {
c = listNodeValue(ln);
c = listNodeValue(ln);
if (server.maxidletime &&
if (server.maxidletime &&
!(c->flags & REDIS_SLAVE) && /* no timeout for slaves */
!(c->flags & REDIS_SLAVE) && /* no timeout for slaves */
...
@@ -1711,10 +1712,11 @@ static void glueReplyBuffersIfNeeded(redisClient *c) {
...
@@ -1711,10 +1712,11 @@ static void glueReplyBuffersIfNeeded(redisClient *c) {
int copylen = 0;
int copylen = 0;
char buf[GLUEREPLY_UP_TO];
char buf[GLUEREPLY_UP_TO];
listNode *ln;
listNode *ln;
listIter li;
robj *o;
robj *o;
listRewind
(
c
->
reply
);
listRewind(c->reply
,&li
);
while
((
ln
=
list
Yield
(
c
->
reply
)))
{
while((ln = list
Next(&li
))) {
int objlen;
int objlen;
o = ln->value;
o = ln->value;
...
@@ -2076,6 +2078,7 @@ static int processCommand(redisClient *c) {
...
@@ -2076,6 +2078,7 @@ static int processCommand(redisClient *c) {
static void replicationFeedSlaves(list *slaves, struct redisCommand *cmd, int dictid, robj **argv, int argc) {
static void replicationFeedSlaves(list *slaves, struct redisCommand *cmd, int dictid, robj **argv, int argc) {
listNode *ln;
listNode *ln;
listIter li;
int outc = 0, j;
int outc = 0, j;
robj **outv;
robj **outv;
/* (args*2)+1 is enough room for args, spaces, newlines */
/* (args*2)+1 is enough room for args, spaces, newlines */
...
@@ -2106,8 +2109,8 @@ static void replicationFeedSlaves(list *slaves, struct redisCommand *cmd, int di
...
@@ -2106,8 +2109,8 @@ static void replicationFeedSlaves(list *slaves, struct redisCommand *cmd, int di
* be sure to free objects if there is no slave in a replication state
* be sure to free objects if there is no slave in a replication state
* able to be feed with commands */
* able to be feed with commands */
for (j = 0; j < outc; j++) incrRefCount(outv[j]);
for (j = 0; j < outc; j++) incrRefCount(outv[j]);
listRewind
(
slaves
);
listRewind(slaves
,&li
);
while
((
ln
=
list
Yield
(
slaves
)))
{
while((ln = list
Next(&li
))) {
redisClient *slave = ln->value;
redisClient *slave = ln->value;
/* Don't feed slaves that are still waiting for BGSAVE to start */
/* Don't feed slaves that are still waiting for BGSAVE to start */
...
@@ -2922,11 +2925,12 @@ static int rdbSaveObject(FILE *fp, robj *o) {
...
@@ -2922,11 +2925,12 @@ static int rdbSaveObject(FILE *fp, robj *o) {
} else if (o->type == REDIS_LIST) {
} else if (o->type == REDIS_LIST) {
/* Save a list value */
/* Save a list value */
list *list = o->ptr;
list *list = o->ptr;
listIter li;
listNode *ln;
listNode *ln;
listRewind
(
list
);
if (rdbSaveLen(fp,listLength(list)) == -1) return -1;
if (rdbSaveLen(fp,listLength(list)) == -1) return -1;
while
((
ln
=
listYield
(
list
)))
{
listRewind(list,&li);
while((ln = listNext(&li))) {
robj *eleobj = listNodeValue(ln);
robj *eleobj = listNodeValue(ln);
if (rdbSaveStringObject(fp,eleobj) == -1) return -1;
if (rdbSaveStringObject(fp,eleobj) == -1) return -1;
...
@@ -5362,9 +5366,10 @@ static void sortCommand(redisClient *c) {
...
@@ -5362,9 +5366,10 @@ static void sortCommand(redisClient *c) {
if (sortval->type == REDIS_LIST) {
if (sortval->type == REDIS_LIST) {
list *list = sortval->ptr;
list *list = sortval->ptr;
listNode *ln;
listNode *ln;
listIter li;
listRewind
(
list
);
listRewind(list
,&li
);
while
((
ln
=
list
Yield
(
list
)))
{
while((ln = list
Next(&li
))) {
robj *ele = ln->value;
robj *ele = ln->value;
vector[j].obj = ele;
vector[j].obj = ele;
vector[j].u.score = 0;
vector[j].u.score = 0;
...
@@ -5392,6 +5397,8 @@ static void sortCommand(redisClient *c) {
...
@@ -5392,6 +5397,8 @@ static void sortCommand(redisClient *c) {
}
}
dictReleaseIterator(di);
dictReleaseIterator(di);
}
}
printf("**************************** %d == %d\n",
j, vectorlen);
redisAssert(j == vectorlen);
redisAssert(j == vectorlen);
/* Now it's time to load the right scores in the sorting vector */
/* Now it's time to load the right scores in the sorting vector */
...
@@ -5460,13 +5467,15 @@ static void sortCommand(redisClient *c) {
...
@@ -5460,13 +5467,15 @@ static void sortCommand(redisClient *c) {
addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",outputlen));
addReplySds(c,sdscatprintf(sdsempty(),"*%d\r\n",outputlen));
for (j = start; j <= end; j++) {
for (j = start; j <= end; j++) {
listNode *ln;
listNode *ln;
listIter li;
if (!getop) {
if (!getop) {
addReplyBulkLen(c,vector[j].obj);
addReplyBulkLen(c,vector[j].obj);
addReply(c,vector[j].obj);
addReply(c,vector[j].obj);
addReply(c,shared.crlf);
addReply(c,shared.crlf);
}
}
listRewind
(
operations
);
listRewind(operations
,&li
);
while
((
ln
=
list
Yield
(
operations
)))
{
while((ln = list
Next(&li
))) {
redisSortOperation *sop = ln->value;
redisSortOperation *sop = ln->value;
robj *val = lookupKeyByPattern(c->db,sop->pattern,
robj *val = lookupKeyByPattern(c->db,sop->pattern,
vector[j].obj);
vector[j].obj);
...
@@ -5491,12 +5500,14 @@ static void sortCommand(redisClient *c) {
...
@@ -5491,12 +5500,14 @@ static void sortCommand(redisClient *c) {
/* STORE option specified, set the sorting result as a List object */
/* STORE option specified, set the sorting result as a List object */
for (j = start; j <= end; j++) {
for (j = start; j <= end; j++) {
listNode *ln;
listNode *ln;
listIter li;
if (!getop) {
if (!getop) {
listAddNodeTail(listPtr,vector[j].obj);
listAddNodeTail(listPtr,vector[j].obj);
incrRefCount(vector[j].obj);
incrRefCount(vector[j].obj);
}
}
listRewind
(
operations
);
listRewind(operations
,&li
);
while
((
ln
=
list
Yield
(
operations
)))
{
while((ln = list
Next(&li
))) {
redisSortOperation *sop = ln->value;
redisSortOperation *sop = ln->value;
robj *val = lookupKeyByPattern(c->db,sop->pattern,
robj *val = lookupKeyByPattern(c->db,sop->pattern,
vector[j].obj);
vector[j].obj);
...
@@ -6136,9 +6147,10 @@ static void syncCommand(redisClient *c) {
...
@@ -6136,9 +6147,10 @@ static void syncCommand(redisClient *c) {
* registering differences since the server forked to save */
* registering differences since the server forked to save */
redisClient *slave;
redisClient *slave;
listNode *ln;
listNode *ln;
listIter li;
listRewind
(
server
.
slaves
);
listRewind(server.slaves
,&li
);
while
((
ln
=
list
Yield
(
server
.
slaves
)))
{
while((ln = list
Next(&li
))) {
slave = ln->value;
slave = ln->value;
if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) break;
if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_END) break;
}
}
...
@@ -6235,9 +6247,10 @@ static void sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) {
...
@@ -6235,9 +6247,10 @@ static void sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) {
static void updateSlavesWaitingBgsave(int bgsaveerr) {
static void updateSlavesWaitingBgsave(int bgsaveerr) {
listNode *ln;
listNode *ln;
int startbgsave = 0;
int startbgsave = 0;
listIter li;
listRewind
(
server
.
slaves
);
listRewind(server.slaves
,&li
);
while
((
ln
=
list
Yield
(
server
.
slaves
)))
{
while((ln = list
Next(&li
))) {
redisClient *slave = ln->value;
redisClient *slave = ln->value;
if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) {
if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START) {
...
@@ -6269,9 +6282,11 @@ static void updateSlavesWaitingBgsave(int bgsaveerr) {
...
@@ -6269,9 +6282,11 @@ static void updateSlavesWaitingBgsave(int bgsaveerr) {
}
}
if (startbgsave) {
if (startbgsave) {
if (rdbSaveBackground(server.dbfilename) != REDIS_OK) {
if (rdbSaveBackground(server.dbfilename) != REDIS_OK) {
listRewind
(
server
.
slaves
);
listIter li;
listRewind(server.slaves,&li);
redisLog(REDIS_WARNING,"SYNC failed. BGSAVE failed");
redisLog(REDIS_WARNING,"SYNC failed. BGSAVE failed");
while
((
ln
=
list
Yield
(
server
.
slaves
)))
{
while((ln = list
Next(&li
))) {
redisClient *slave = ln->value;
redisClient *slave = ln->value;
if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START)
if (slave->replstate == REDIS_REPL_WAIT_BGSAVE_START)
...
@@ -6792,9 +6807,10 @@ static int rewriteAppendOnlyFile(char *filename) {
...
@@ -6792,9 +6807,10 @@ static int rewriteAppendOnlyFile(char *filename) {
/* Emit the RPUSHes needed to rebuild the list */
/* Emit the RPUSHes needed to rebuild the list */
list *list = o->ptr;
list *list = o->ptr;
listNode *ln;
listNode *ln;
listIter li;
listRewind
(
list
);
listRewind(list
,&li
);
while
((
ln
=
list
Yield
(
list
)))
{
while((ln = list
Next(&li
))) {
char cmd[]="*3\r\n$5\r\nRPUSH\r\n";
char cmd[]="*3\r\n$5\r\nRPUSH\r\n";
robj *eleobj = listNodeValue(ln);
robj *eleobj = listNodeValue(ln);
...
@@ -7080,7 +7096,7 @@ static int vmFreePage(off_t page) {
...
@@ -7080,7 +7096,7 @@ static int vmFreePage(off_t page) {
* note: I implemented this function just after watching an episode of
* note: I implemented this function just after watching an episode of
* Battlestar Galactica, where the hybrid was continuing to say "JUMP!"
* Battlestar Galactica, where the hybrid was continuing to say "JUMP!"
*/
*/
static
int
vmFindContiguousPages
(
off_t
*
first
,
in
t
n
)
{
static int vmFindContiguousPages(off_t *first,
off_
t n) {
off_t base, offset = 0, since_jump = 0, numfree = 0;
off_t base, offset = 0, since_jump = 0, numfree = 0;
if (server.vm_near_pages == REDIS_VM_MAX_NEAR_PAGES) {
if (server.vm_near_pages == REDIS_VM_MAX_NEAR_PAGES) {
...
@@ -7469,6 +7485,10 @@ static void vmThreadedIOCompletedJob(aeEventLoop *el, int fd, void *privdata,
...
@@ -7469,6 +7485,10 @@ static void vmThreadedIOCompletedJob(aeEventLoop *el, int fd, void *privdata,
/* Ooops... no space! */
/* Ooops... no space! */
freeIOJob(j);
freeIOJob(j);
} else {
} else {
/* Note that we need to mark this pages as used now,
* if the job will be canceled, we'll mark them as freed
* again. */
vmMarkPagesUsed(j->page,j->pages);
j->type = REDIS_IOJOB_DO_SWAP;
j->type = REDIS_IOJOB_DO_SWAP;
lockThreadedIO();
lockThreadedIO();
queueIOJob(j);
queueIOJob(j);
...
@@ -7494,7 +7514,6 @@ static void vmThreadedIOCompletedJob(aeEventLoop *el, int fd, void *privdata,
...
@@ -7494,7 +7514,6 @@ static void vmThreadedIOCompletedJob(aeEventLoop *el, int fd, void *privdata,
key->vtype = j->val->type;
key->vtype = j->val->type;
decrRefCount(val); /* Deallocate the object from memory. */
decrRefCount(val); /* Deallocate the object from memory. */
dictGetEntryVal(de) = NULL;
dictGetEntryVal(de) = NULL;
vmMarkPagesUsed
(
j
->
page
,
j
->
pages
);
redisLog(REDIS_DEBUG,
redisLog(REDIS_DEBUG,
"VM: object %s swapped out at %lld (%lld pages) (threaded)",
"VM: object %s swapped out at %lld (%lld pages) (threaded)",
(unsigned char*) key->ptr,
(unsigned char*) key->ptr,
...
@@ -7549,9 +7568,10 @@ static void vmCancelThreadedIOJob(robj *o) {
...
@@ -7549,9 +7568,10 @@ static void vmCancelThreadedIOJob(robj *o) {
/* Search for a matching key in one of the queues */
/* Search for a matching key in one of the queues */
for (i = 0; i < 3; i++) {
for (i = 0; i < 3; i++) {
listNode *ln;
listNode *ln;
listIter li;
listRewind
(
lists
[
i
]);
listRewind(lists[i]
,&li
);
while
((
ln
=
list
Yield
(
lists
[
i
]
))
!=
NULL
)
{
while ((ln = list
Next(&li
)) != NULL) {
iojob *job = ln->value;
iojob *job = ln->value;
if (job->canceled) continue; /* Skip this, already canceled. */
if (job->canceled) continue; /* Skip this, already canceled. */
...
@@ -7570,6 +7590,12 @@ static void vmCancelThreadedIOJob(robj *o) {
...
@@ -7570,6 +7590,12 @@ static void vmCancelThreadedIOJob(robj *o) {
job->canceled = 1;
job->canceled = 1;
break;
break;
}
}
/* Mark the pages as free since the swap didn't happened
* or happened but is not discarded. */
if (job->type == REDIS_IOJOB_DO_SWAP)
vmMarkPagesFree(job->page,job->pages);
/* Finally we have to adjust the storage type of the object
* in order to "UNDO" the operaiton. */
if (o->storage == REDIS_VM_LOADING)
if (o->storage == REDIS_VM_LOADING)
o->storage = REDIS_VM_SWAPPED;
o->storage = REDIS_VM_SWAPPED;
else if (o->storage == REDIS_VM_SWAPPING)
else if (o->storage == REDIS_VM_SWAPPING)
...
...
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