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
b454056d
Commit
b454056d
authored
Aug 18, 2011
by
Pieter Noordhuis
Committed by
antirez
Sep 13, 2011
Browse files
Asynchronously close old file after BGREWRITEAOF
parent
b1c892f3
Changes
1
Hide whitespace changes
Inline
Side-by-side
src/aof.c
View file @
b454056d
...
@@ -669,56 +669,119 @@ void aofUpdateCurrentSize(void) {
...
@@ -669,56 +669,119 @@ void aofUpdateCurrentSize(void) {
* Handle this. */
* Handle this. */
void
backgroundRewriteDoneHandler
(
int
exitcode
,
int
bysignal
)
{
void
backgroundRewriteDoneHandler
(
int
exitcode
,
int
bysignal
)
{
if
(
!
bysignal
&&
exitcode
==
0
)
{
if
(
!
bysignal
&&
exitcode
==
0
)
{
int
fd
;
int
newfd
,
oldfd
;
int
nwritten
;
char
tmpfile
[
256
];
char
tmpfile
[
256
];
long
long
now
=
ustime
();
redisLog
(
REDIS_NOTICE
,
redisLog
(
REDIS_NOTICE
,
"Background append only file rewriting terminated with success"
);
"Background AOF rewrite terminated with success"
);
/* Now it's time to flush the differences accumulated by the parent */
snprintf
(
tmpfile
,
256
,
"temp-rewriteaof-bg-%d.aof"
,
(
int
)
server
.
bgrewritechildpid
);
/* Flush the differences accumulated by the parent to the rewritten AOF. */
fd
=
open
(
tmpfile
,
O_WRONLY
|
O_APPEND
);
snprintf
(
tmpfile
,
256
,
"temp-rewriteaof-bg-%d.aof"
,
(
int
)
server
.
bgrewritechildpid
);
if
(
fd
==
-
1
)
{
newfd
=
open
(
tmpfile
,
O_WRONLY
|
O_APPEND
);
redisLog
(
REDIS_WARNING
,
"Not able to open the temp append only file produced by the child: %s"
,
strerror
(
errno
));
if
(
newfd
==
-
1
)
{
redisLog
(
REDIS_WARNING
,
"Unable to open the temporary AOF produced by the child: %s"
,
strerror
(
errno
));
goto
cleanup
;
goto
cleanup
;
}
}
/* Flush our data... */
if
(
write
(
fd
,
server
.
bgrewritebuf
,
sdslen
(
server
.
bgrewritebuf
))
!=
nwritten
=
write
(
newfd
,
server
.
bgrewritebuf
,
sdslen
(
server
.
bgrewritebuf
));
(
signed
)
sdslen
(
server
.
bgrewritebuf
))
{
if
(
nwritten
!=
(
signed
)
sdslen
(
server
.
bgrewritebuf
))
{
redisLog
(
REDIS_WARNING
,
"Error or short write trying to flush the parent diff of the append log file in the child temp file: %s"
,
strerror
(
errno
));
if
(
nwritten
==
-
1
)
{
close
(
fd
);
redisLog
(
REDIS_WARNING
,
"Error trying to flush the parent diff to the rewritten AOF: %s"
,
strerror
(
errno
));
}
else
{
redisLog
(
REDIS_WARNING
,
"Short write trying to flush the parent diff to the rewritten AOF: %s"
,
strerror
(
errno
));
}
close
(
newfd
);
goto
cleanup
;
goto
cleanup
;
}
}
redisLog
(
REDIS_NOTICE
,
"Parent diff flushed into the new append log file with success (%lu bytes)"
,
sdslen
(
server
.
bgrewritebuf
));
/* Now our work is to rename the temp file into the stable file. And
redisLog
(
REDIS_NOTICE
,
* switch the file descriptor used by the server for append only. */
"Parent diff successfully flushed to the rewritten AOF (%lu bytes)"
,
nwritten
);
/* The only remaining thing to do is to rename the temporary file to
* the configured file and switch the file descriptor used to do AOF
* writes. There are two possible scenarios:
*
* 1) AOF is DISABLED and this was a one time rewrite. The temporary
* file will be renamed to the configured file. When this file already
* exists, it will be unlinked, which may block the server.
*
* 2) AOF is ENABLED and the rewritten AOF will immediately start
* receiving writes. After the temporary file is renamed to the
* configured file, the original AOF file descriptor will be closed.
* Since this will be the last reference to that file, closing it
* causes the underlying file to be unlinked, which may block the
* server.
*
* To mitigate the blocking effect of the unlink operation (either
* caused by rename(2) in scenario 1, or by close(2) in scenario 2), we
* use a background thread in libeio to take care of this. First, we
* make scenario 1 identical to scenario 2 by opening the target file
* when it exists. The unlink operation after the rename(2) will then
* be executed upon calling close(2) for its descriptor. Everything to
* guarantee atomicity for this switch has already happened by then, so
* we don't care what the outcome or duration of that close operation
* is, as long as the file descriptor is released again. */
if
(
server
.
appendfd
==
-
1
)
{
/* AOF disabled */
struct
stat
st
;
/* Check if the configured filename exists. If so, we need to open
* it to prevent rename(2) from unlinking it. */
if
(
stat
(
server
.
appendfilename
,
&
st
)
==
ENOENT
)
{
oldfd
=
-
1
;
}
else
{
/* Don't care if this fails: oldfd will be -1. */
oldfd
=
open
(
server
.
appendfilename
,
O_RDONLY
|
O_NONBLOCK
);
}
}
else
{
/* AOF enabled */
oldfd
=
-
1
;
}
/* Rename the temporary file. This will not unlink the target file if
* it exists, because we reference it with "oldfd". */
if
(
rename
(
tmpfile
,
server
.
appendfilename
)
==
-
1
)
{
if
(
rename
(
tmpfile
,
server
.
appendfilename
)
==
-
1
)
{
redisLog
(
REDIS_WARNING
,
"Can't rename the temp append only file into the stable one: %s"
,
strerror
(
errno
));
redisLog
(
REDIS_WARNING
,
close
(
fd
);
"Error trying to rename the temporary AOF: %s"
,
strerror
(
errno
));
close
(
newfd
);
if
(
oldfd
!=
-
1
)
close
(
oldfd
);
goto
cleanup
;
goto
cleanup
;
}
}
/* Mission completed... almost */
redisLog
(
REDIS_NOTICE
,
"Append only file successfully rewritten."
);
if
(
server
.
appendfd
==
-
1
)
{
if
(
server
.
appendfd
!=
-
1
)
{
/* AOF disabled */
/* If append only is actually enabled... */
close
(
newfd
);
close
(
server
.
appendfd
);
}
else
{
server
.
appendfd
=
fd
;
/* AOF enabled */
if
(
server
.
appendfsync
!=
APPENDFSYNC_NO
)
aof_fsync
(
fd
);
oldfd
=
server
.
appendfd
;
server
.
appendseldb
=
-
1
;
/* Make sure it will issue SELECT */
server
.
appendfd
=
newfd
;
redisLog
(
REDIS_NOTICE
,
"The new append only file was selected for future appends."
);
if
(
server
.
appendfsync
!=
APPENDFSYNC_NO
)
aof_fsync
(
newfd
);
server
.
appendseldb
=
-
1
;
/* Make sure SELECT is re-issued */
aofUpdateCurrentSize
();
aofUpdateCurrentSize
();
server
.
auto_aofrewrite_base_size
=
server
.
appendonly_current_size
;
server
.
auto_aofrewrite_base_size
=
server
.
appendonly_current_size
;
}
else
{
/* If append only is disabled we just generate a dump in this
* format. Why not? */
close
(
fd
);
}
}
redisLog
(
REDIS_NOTICE
,
"Background AOF rewrite successful"
);
/* Asynchronously close the overwritten AOF. */
if
(
oldfd
!=
-
1
)
eio_close
(
oldfd
,
0
,
NULL
,
0
);
redisLog
(
REDIS_VERBOSE
,
"Background AOF rewrite signal handler took %lldus"
,
ustime
()
-
now
);
}
else
if
(
!
bysignal
&&
exitcode
!=
0
)
{
}
else
if
(
!
bysignal
&&
exitcode
!=
0
)
{
redisLog
(
REDIS_WARNING
,
"Background append only file rewriting error"
);
redisLog
(
REDIS_WARNING
,
"Background AOF rewrite terminated with error"
);
}
else
{
}
else
{
redisLog
(
REDIS_WARNING
,
redisLog
(
REDIS_WARNING
,
"Background append only file rewriting terminated by signal %d"
,
"Background AOF rewrite terminated by signal %d"
,
bysignal
);
bysignal
);
}
}
cleanup:
cleanup:
sdsfree
(
server
.
bgrewritebuf
);
sdsfree
(
server
.
bgrewritebuf
);
server
.
bgrewritebuf
=
sdsempty
();
server
.
bgrewritebuf
=
sdsempty
();
...
...
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