}
do {
- prepareForBenchmark();
- c = createClient();
- if (!c) exit(1);
- c->obuf = sdscat(c->obuf,"PING\r\n");
- c->replytype = REPLY_RETCODE;
- createMissingClients(c);
- aeMain(config.el);
- endBenchmark("PING");
-
prepareForBenchmark();
c = createClient();
if (!c) exit(1);
aeMain(config.el);
endBenchmark("LPOP");
+ prepareForBenchmark();
+ c = createClient();
+ if (!c) exit(1);
+ c->obuf = sdscat(c->obuf,"PING\r\n");
+ c->replytype = REPLY_RETCODE;
+ createMissingClients(c);
+ aeMain(config.el);
+ endBenchmark("PING");
+
printf("\n");
} while(config.loop);
<div class="narrow">
<h1><a name="LREM _key_ _count_ _value_">LREM _key_ _count_ _value_</a></h1>
-<i>Time complexity: O(N) (with N being the length of the list)</i><blockquote>Remove the first <i>count</i> occurrences of the <i>value</i> element from the list.If <i>count</i> is zero all the elements are removed. If <i>count</i> is negativeelements are removed from tail to head, instead to go from head to tailthat is the normal behaviour. So for example LREM with count -2 and_hello_ as value to remove against the list (a,b,c,hello,x,hello,hello) willlave the list (a,b,c,hello,x). The number of removed elements is returnedas an integer, see below for more information aboht the returned value.</blockquote>
+<i>Time complexity: O(N) (with N being the length of the list)</i><blockquote>Remove the first <i>count</i> occurrences of the <i>value</i> element from the list.If <i>count</i> is zero all the elements are removed. If <i>count</i> is negativeelements are removed from tail to head, instead to go from head to tailthat is the normal behaviour. So for example LREM with count -2 and_hello_ as value to remove against the list (a,b,c,hello,x,hello,hello) willlave the list (a,b,c,hello,x). The number of removed elements is returnedas an integer, see below for more information about the returned value.Note that non existing keys are considered like empty lists by LREM, so LREMagainst non existing keys will always return 0.</blockquote>
<h2><a name="Return value">Return value</a></h2><a href="ReplyTypes.html">Integer Reply</a>, specifically:<br/><br/><pre class="codeblock python" name="code">
The number of removed elements if the operation succeeded
</pre><h2><a name="See also">See also</a></h2>
int daemonize;
char *pidfile;
int bgsaveinprogress;
+ pid_t bgsavechildpid;
struct saveparam *saveparams;
int saveparamslen;
char *logfile;
/* XXX: TODO handle the case of the saving child killed */
if (wait4(-1,&statloc,WNOHANG,NULL)) {
int exitcode = WEXITSTATUS(statloc);
- if (exitcode == 0) {
+ int bysignal = WIFSIGNALED(statloc);
+
+ if (!bysignal && exitcode == 0) {
redisLog(REDIS_NOTICE,
"Background saving terminated with success");
server.dirty = 0;
server.lastsave = time(NULL);
+ } else if (!bysignal && exitcode != 0) {
+ redisLog(REDIS_WARNING, "Background saving error");
} else {
redisLog(REDIS_WARNING,
- "Background saving error");
+ "Background saving terminated by signal");
}
server.bgsaveinprogress = 0;
+ server.bgsavechildpid = -1;
updateSalvesWaitingBgsave(exitcode == 0 ? REDIS_OK : REDIS_ERR);
}
} else {
}
server.cronloops = 0;
server.bgsaveinprogress = 0;
+ server.bgsavechildpid = -1;
server.lastsave = time(NULL);
server.dirty = 0;
server.usedmemory = 0;
}
redisLog(REDIS_NOTICE,"Background saving started by pid %d",childpid);
server.bgsaveinprogress = 1;
+ server.bgsavechildpid = childpid;
return REDIS_OK;
}
return REDIS_OK; /* unreached */
static void shutdownCommand(redisClient *c) {
redisLog(REDIS_WARNING,"User requested shutdown, saving DB...");
- /* XXX: TODO kill the child if there is a bgsave in progress */
+ if (server.bgsaveinprogress) {
+ redisLog(REDIS_WARNING,"There is a live saving child. Killing it!");
+ kill(server.bgsavechildpid,SIGKILL);
+ }
if (rdbSave(server.dbfilename) == REDIS_OK) {
- if (server.daemonize) {
+ if (server.daemonize)
unlink(server.pidfile);
- }
redisLog(REDIS_WARNING,"%zu bytes used at exit",zmalloc_used_memory());
redisLog(REDIS_WARNING,"Server exit now, bye bye...");
exit(1);