1
0
mirror of https://github.com/apple/foundationdb.git synced 2025-05-17 03:12:21 +08:00

Backup describe, expire, and delete will now clearly indicate when there is no backup at the given URL.

This commit is contained in:
Stephen Atherton 2018-12-20 18:05:23 -08:00
parent 567a7bd58a
commit f64d5321e9
6 changed files with 43 additions and 2 deletions

@ -1901,12 +1901,11 @@ ACTOR Future<Void> deleteBackupContainer(const char *name, std::string destinati
state Future<Void> done = c->deleteContainer(&numDeleted); state Future<Void> done = c->deleteContainer(&numDeleted);
state int lastUpdate = -1; state int lastUpdate = -1;
printf("Deleting data...\n"); printf("Deleting %s...\n", destinationContainer.c_str());
loop { loop {
choose { choose {
when ( Void _ = wait(done) ) { when ( Void _ = wait(done) ) {
printf("The entire container has been deleted.\n");
break; break;
} }
when ( Void _ = wait(delay(5)) ) { when ( Void _ = wait(delay(5)) ) {
@ -1918,6 +1917,7 @@ ACTOR Future<Void> deleteBackupContainer(const char *name, std::string destinati
} }
} }
printf("\r%d objects deleted\n", numDeleted); printf("\r%d objects deleted\n", numDeleted);
printf("The entire container has been deleted.\n");
} }
catch (Error& e) { catch (Error& e) {
if(e.code() == error_code_actor_cancelled) if(e.code() == error_code_actor_cancelled)

@ -200,6 +200,7 @@ public:
// Create the container // Create the container
virtual Future<Void> create() = 0; virtual Future<Void> create() = 0;
virtual Future<bool> exists() = 0;
// Get a list of fileNames and their sizes in the container under the given path // 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 // Although not required, an implementation can avoid traversing unwanted subfolders
@ -550,6 +551,12 @@ public:
.detail("URL", bc->getURL()) .detail("URL", bc->getURL())
.detail("LogStartVersionOverride", logStartVersionOverride); .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 // 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. // from which to resolve the relative version.
// This could be handled more efficiently without recursion but it's tricky, this will do for now. // This could be handled more efficiently without recursion but it's tricky, this will do for now.
@ -1115,6 +1122,11 @@ public:
return Void(); return Void();
} }
// The container exists if the folder it resides in exists
Future<bool> exists() {
return directoryExists(m_path);
}
Future<Reference<IAsyncFile>> readFile(std::string path) { Future<Reference<IAsyncFile>> readFile(std::string path) {
int flags = IAsyncFile::OPEN_NO_AIO | IAsyncFile::OPEN_READONLY | IAsyncFile::OPEN_UNCACHED; 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, // 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<BackupContainerBlobStore>::addRef(this)); return create_impl(Reference<BackupContainerBlobStore>::addRef(this));
} }
// The container exists if the index entry in the blob bucket exists
Future<bool> exists() {
return m_bstore->objectExists(m_bucket, indexEntry());
}
ACTOR static Future<Void> deleteContainer_impl(Reference<BackupContainerBlobStore> bc, int *pNumDeleted) { ACTOR static Future<Void> deleteContainer_impl(Reference<BackupContainerBlobStore> 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 // First delete everything under the data prefix in the bucket
Void _ = wait(bc->m_bstore->deleteRecursively(bc->m_bucket, bc->dataPath(""), pNumDeleted)); Void _ = wait(bc->m_bstore->deleteRecursively(bc->m_bucket, bc->dataPath(""), pNumDeleted));

@ -162,6 +162,7 @@ public:
// Create the container // Create the container
virtual Future<Void> create() = 0; virtual Future<Void> create() = 0;
virtual Future<bool> exists() = 0;
// Open a log file or range file for writing // Open a log file or range file for writing
virtual Future<Reference<IBackupFile>> writeLogFile(Version beginVersion, Version endVersion, int blockSize) = 0; virtual Future<Reference<IBackupFile>> writeLogFile(Version beginVersion, Version endVersion, int blockSize) = 0;

@ -2062,6 +2062,19 @@ bool fileExists(std::string const& filename) {
return true; 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) { int64_t fileSize(std::string const& filename) {
#ifdef _WIN32 #ifdef _WIN32
struct _stati64 file_status; struct _stati64 file_status;

@ -285,6 +285,9 @@ void threadYield(); // Attempt to yield to other processes or threads
// Returns true iff the file exists // Returns true iff the file exists
bool fileExists(std::string const& filename); bool fileExists(std::string const& filename);
// Returns true iff the directory exists
bool directoryExists(std::string const& path);
// Returns size of file in bytes // Returns size of file in bytes
int64_t fileSize(std::string const& filename); int64_t fileSize(std::string const& filename);

@ -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_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_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_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_invalid_version, 2361, "Invalid restore version")
ERROR( restore_corrupted_data, 2362, "Corrupted backup data") ERROR( restore_corrupted_data, 2362, "Corrupted backup data")
ERROR( restore_missing_data, 2363, "Missing backup data") ERROR( restore_missing_data, 2363, "Missing backup data")