diff options
author | antirez <antirez@gmail.com> | 2020-03-04 11:10:54 +0100 |
---|---|---|
committer | antirez <antirez@gmail.com> | 2020-03-05 12:51:14 +0100 |
commit | baaf869fc3e138cfcb4cfda09f09fd3c87c8f924 (patch) | |
tree | 737c9ebd60f015ccda4c84efa4f45972ac6e9922 | |
parent | be4bc1a5be26a7fde2fd05acd8187f5f0ed59f25 (diff) | |
download | redis-baaf869fc3e138cfcb4cfda09f09fd3c87c8f924.tar.gz |
Introduce bg_unlink().
-rw-r--r-- | src/replication.c | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/src/replication.c b/src/replication.c index e71b269d8..8a05b9696 100644 --- a/src/replication.c +++ b/src/replication.c @@ -79,6 +79,34 @@ char *replicationGetSlaveName(client *c) { return buf; } +/* Plain unlink() can block for quite some time in order to actually apply + * the file deletion to the filesystem. This call removes the file in a + * background thread instead. We actually just do close() in the thread, + * by using the fact that if there is another instance of the same file open, + * the foreground unlink() will not really do anything, and deleting the + * file will only happen once the last reference is lost. */ +int bg_unlink(const char *filename) { + int fd = open(filename,O_RDONLY|O_NONBLOCK); + if (fd == -1) { + /* Can't open the file? Fall back to unlinking in the main thread. */ + return unlink(filename); + } else { + /* The following unlink() will not do anything since file + * is still open. */ + int retval = unlink(filename); + if (retval == -1) { + /* If we got an unlink error, we just return it, closing the + * new reference we have to the file. */ + int old_errno = errno; + close(fd); /* This would overwrite our errno. So we saved it. */ + errno = old_errno; + return -1; + } + bioCreateBackgroundJob(BIO_CLOSE_FILE,(void*)(long)fd,NULL,NULL); + return 0; /* Success. */ + } +} + /* ---------------------------------- MASTER -------------------------------- */ void createReplicationBacklog(void) { @@ -917,7 +945,7 @@ void removeRDBUsedToSyncReplicas(void) { } if (delrdb) { RDBGeneratedByReplication = 0; - unlink(server.rdb_filename); + bg_unlink(server.rdb_filename); } } } @@ -1679,14 +1707,14 @@ void readSyncBulkPayload(connection *conn) { "Failed trying to load the MASTER synchronization " "DB from disk"); cancelReplicationHandshake(); - if (allPersistenceDisabled()) unlink(server.rdb_filename); + if (allPersistenceDisabled()) bg_unlink(server.rdb_filename); /* Note that there's no point in restarting the AOF on sync failure, it'll be restarted when sync succeeds or replica promoted. */ return; } /* Cleanup. */ - if (allPersistenceDisabled()) unlink(server.rdb_filename); + if (allPersistenceDisabled()) bg_unlink(server.rdb_filename); zfree(server.repl_transfer_tmpfile); close(server.repl_transfer_fd); server.repl_transfer_fd = -1; |