From f64d5321e9507a54845d8e257b7051186c22e41c Mon Sep 17 00:00:00 2001 From: Stephen Atherton Date: Thu, 20 Dec 2018 18:05:23 -0800 Subject: [PATCH] Backup describe, expire, and delete will now clearly indicate when there is no backup at the given URL. --- fdbbackup/backup.actor.cpp | 4 ++-- fdbclient/BackupContainer.actor.cpp | 23 +++++++++++++++++++++++ fdbclient/BackupContainer.h | 1 + flow/Platform.cpp | 13 +++++++++++++ flow/Platform.h | 3 +++ flow/error_definitions.h | 1 + 6 files changed, 43 insertions(+), 2 deletions(-) diff --git a/fdbbackup/backup.actor.cpp b/fdbbackup/backup.actor.cpp index 29bdfe2a18..f6c73fcbb2 100644 --- a/fdbbackup/backup.actor.cpp +++ b/fdbbackup/backup.actor.cpp @@ -1901,12 +1901,11 @@ ACTOR Future deleteBackupContainer(const char *name, std::string destinati state Future done = c->deleteContainer(&numDeleted); state int lastUpdate = -1; - printf("Deleting data...\n"); + printf("Deleting %s...\n", destinationContainer.c_str()); loop { choose { when ( Void _ = wait(done) ) { - printf("The entire container has been deleted.\n"); break; } when ( Void _ = wait(delay(5)) ) { @@ -1918,6 +1917,7 @@ ACTOR Future deleteBackupContainer(const char *name, std::string destinati } } printf("\r%d objects deleted\n", numDeleted); + printf("The entire container has been deleted.\n"); } catch (Error& e) { if(e.code() == error_code_actor_cancelled) diff --git a/fdbclient/BackupContainer.actor.cpp b/fdbclient/BackupContainer.actor.cpp index 23cce6a28e..a83292039f 100644 --- a/fdbclient/BackupContainer.actor.cpp +++ b/fdbclient/BackupContainer.actor.cpp @@ -200,6 +200,7 @@ public: // Create the container virtual Future create() = 0; + virtual Future exists() = 0; // Get a list of fileNames and their sizes in the container under the given path // Although not required, an implementation can avoid traversing unwanted subfolders @@ -550,6 +551,12 @@ public: .detail("URL", bc->getURL()) .detail("LogStartVersionOverride", logStartVersionOverride); + bool e = wait(bc->exists()); + if(!e) { + TraceEvent(SevWarnAlways, "BackupContainerDoesNotExist").detail("URL", bc->getURL()); + throw backup_does_not_exist(); + } + // If logStartVersion is relative, then first do a recursive call without it to find the max log version // from which to resolve the relative version. // This could be handled more efficiently without recursion but it's tricky, this will do for now. @@ -1115,6 +1122,11 @@ public: return Void(); } + // The container exists if the folder it resides in exists + Future exists() { + return directoryExists(m_path); + } + Future> readFile(std::string path) { int flags = IAsyncFile::OPEN_NO_AIO | IAsyncFile::OPEN_READONLY | IAsyncFile::OPEN_UNCACHED; // Simulation does not properly handle opening the same file from multiple machines using a shared filesystem, @@ -1361,7 +1373,18 @@ public: return create_impl(Reference::addRef(this)); } + // The container exists if the index entry in the blob bucket exists + Future exists() { + return m_bstore->objectExists(m_bucket, indexEntry()); + } + ACTOR static Future deleteContainer_impl(Reference bc, int *pNumDeleted) { + bool e = wait(bc->exists()); + if(!e) { + TraceEvent(SevWarnAlways, "BackupContainerDoesNotExist").detail("URL", bc->getURL()); + throw backup_does_not_exist(); + } + // First delete everything under the data prefix in the bucket Void _ = wait(bc->m_bstore->deleteRecursively(bc->m_bucket, bc->dataPath(""), pNumDeleted)); diff --git a/fdbclient/BackupContainer.h b/fdbclient/BackupContainer.h index dc55ea2bed..9154992ec8 100644 --- a/fdbclient/BackupContainer.h +++ b/fdbclient/BackupContainer.h @@ -162,6 +162,7 @@ public: // Create the container virtual Future create() = 0; + virtual Future exists() = 0; // Open a log file or range file for writing virtual Future> writeLogFile(Version beginVersion, Version endVersion, int blockSize) = 0; diff --git a/flow/Platform.cpp b/flow/Platform.cpp index 8b186d5a62..d612eeb174 100644 --- a/flow/Platform.cpp +++ b/flow/Platform.cpp @@ -2062,6 +2062,19 @@ bool fileExists(std::string const& filename) { return true; } +bool directoryExists(std::string const& path) { +#ifdef _WIN32 + DWORD bits = ::GetFileAttributes(path.c_str()); + return bits != INVALID_FILE_ATTRIBUTES && (bits & FILE_ATTRIBUTE_DIRECTORY); +#else + DIR *d = opendir(path.c_str()); + if(d == nullptr) + return false; + closedir(d); + return true; +#endif +} + int64_t fileSize(std::string const& filename) { #ifdef _WIN32 struct _stati64 file_status; diff --git a/flow/Platform.h b/flow/Platform.h index dc998ec4d9..a946a0a8ed 100644 --- a/flow/Platform.h +++ b/flow/Platform.h @@ -285,6 +285,9 @@ void threadYield(); // Attempt to yield to other processes or threads // Returns true iff the file exists bool fileExists(std::string const& filename); +// Returns true iff the directory exists +bool directoryExists(std::string const& path); + // Returns size of file in bytes int64_t fileSize(std::string const& filename); diff --git a/flow/error_definitions.h b/flow/error_definitions.h index c0f6b0445a..d6a5acdcb3 100755 --- a/flow/error_definitions.h +++ b/flow/error_definitions.h @@ -177,6 +177,7 @@ ERROR( backup_invalid_info, 2315, "Backup Container URL invalid") ERROR( backup_cannot_expire, 2316, "Cannot expire requested data from backup without violating minimum restorability") ERROR( backup_auth_missing, 2317, "Cannot find authentication details (such as a password or secret key) for the specified Backup Container URL") ERROR( backup_auth_unreadable, 2318, "Cannot read or parse one or more sources of authentication information for Backup Container URLs") +ERROR( backup_does_not_exist, 2319, "Backup does not exist") ERROR( restore_invalid_version, 2361, "Invalid restore version") ERROR( restore_corrupted_data, 2362, "Corrupted backup data") ERROR( restore_missing_data, 2363, "Missing backup data")