diff options
author | Reinhard Tartler <siretart@tauware.de> | 2017-06-11 21:52:33 -0400 |
---|---|---|
committer | Reinhard Tartler <siretart@tauware.de> | 2017-06-11 21:52:33 -0400 |
commit | e0eb815b67734abd09ff41e2271630d4b2a6d760 (patch) | |
tree | 0df971c34f98d2a1dfd0921524a17d561a4a6536 /lib/raidfile | |
parent | 676c9e1c9d4ac8eb8a440d7f11c4ac44f98f4a6a (diff) | |
parent | e19a5db232e1ef90e9a02159d2fbd9707ffe4373 (diff) |
merge upstream version 0.12
Diffstat (limited to 'lib/raidfile')
-rw-r--r-- | lib/raidfile/RaidFileController.cpp | 13 | ||||
-rw-r--r-- | lib/raidfile/RaidFileController.h | 4 | ||||
-rw-r--r-- | lib/raidfile/RaidFileRead.cpp | 112 | ||||
-rw-r--r-- | lib/raidfile/RaidFileWrite.cpp | 189 | ||||
-rw-r--r-- | lib/raidfile/RaidFileWrite.h | 19 |
5 files changed, 337 insertions, 0 deletions
diff --git a/lib/raidfile/RaidFileController.cpp b/lib/raidfile/RaidFileController.cpp index 2cc6976b..84c2a520 100644 --- a/lib/raidfile/RaidFileController.cpp +++ b/lib/raidfile/RaidFileController.cpp @@ -164,13 +164,26 @@ RaidFileDiscSet &RaidFileController::GetDiscSet(unsigned int DiscSetNum) { if(DiscSetNum < 0 || DiscSetNum >= mSetList.size()) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, NoSuchDiscSet) +======= + THROW_EXCEPTION_MESSAGE(RaidFileException, NoSuchDiscSet, DiscSetNum << + " (" << mSetList.size() << " disc sets configured)") +>>>>>>> 0.12 } return mSetList[DiscSetNum]; } +<<<<<<< HEAD +======= +// Overload to make usable in gdb debugger. +int RaidFileDiscSet::GetSetNumForWriteFiles(const char* filename) const +{ + return GetSetNumForWriteFiles(std::string(filename)); +} +>>>>>>> 0.12 // -------------------------------------------------------------------------- // diff --git a/lib/raidfile/RaidFileController.h b/lib/raidfile/RaidFileController.h index 216bdf3a..b2b8cb0d 100644 --- a/lib/raidfile/RaidFileController.h +++ b/lib/raidfile/RaidFileController.h @@ -49,7 +49,11 @@ public: int GetSetID() const {return mSetID;} int GetSetNumForWriteFiles(const std::string &rFilename) const; +<<<<<<< HEAD +======= + int GetSetNumForWriteFiles(const char* filename) const; +>>>>>>> 0.12 unsigned int GetBlockSize() const {return mBlockSize;} // Is this disc set a non-RAID disc set? (ie files never get transformed to raid storage) diff --git a/lib/raidfile/RaidFileRead.cpp b/lib/raidfile/RaidFileRead.cpp index 0a79be57..3a7a5893 100644 --- a/lib/raidfile/RaidFileRead.cpp +++ b/lib/raidfile/RaidFileRead.cpp @@ -12,7 +12,14 @@ #include <errno.h> #include <fcntl.h> #include <stdarg.h> +<<<<<<< HEAD #include <unistd.h> +======= + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif +>>>>>>> 0.12 #include <sys/stat.h> #include <sys/types.h> @@ -1022,8 +1029,13 @@ std::auto_ptr<RaidFileRead> RaidFileRead::Open(int SetNumber, const std::string RaidFileUtil::ExistType existance = RaidFileUtil::RaidFileExists(rdiscSet, Filename, &startDisc, &existingFiles, pRevisionID); if(existance == RaidFileUtil::NoFile) { +<<<<<<< HEAD BOX_ERROR("Expected raidfile " << Filename << " does not exist"); THROW_EXCEPTION(RaidFileException, RaidFileDoesntExist) +======= + THROW_FILE_ERROR("Expected raidfile does not exist", + Filename, RaidFileException, RaidFileDoesntExist); +>>>>>>> 0.12 } else if(existance == RaidFileUtil::NonRaid) { @@ -1086,9 +1098,25 @@ std::auto_ptr<RaidFileRead> RaidFileRead::Open(int SetNumber, const std::string { stripe2errno = errno; } +<<<<<<< HEAD if(stripe1errno != 0 || stripe2errno != 0) { THROW_EXCEPTION(RaidFileException, ErrorOpeningFileForRead) +======= + + if(stripe1errno != 0) + { + THROW_SYS_FILE_ERRNO("Failed to open RaidFile", + stripe1Filename, stripe1errno, + RaidFileException, ErrorOpeningFileForRead); + } + + if(stripe2errno != 0) + { + THROW_SYS_FILE_ERRNO("Failed to open RaidFile", + stripe2Filename, stripe2errno, + RaidFileException, ErrorOpeningFileForRead); +>>>>>>> 0.12 } // stat stripe 1 to find ('half' of) length... @@ -1107,11 +1135,28 @@ std::auto_ptr<RaidFileRead> RaidFileRead::Open(int SetNumber, const std::string length += st.st_size; // Handle errors +<<<<<<< HEAD if(stripe1errno != 0 || stripe2errno != 0) { THROW_EXCEPTION(RaidFileException, OSError) } +======= + if(stripe1errno != 0) + { + THROW_SYS_FILE_ERRNO("Failed to stat RaidFile", + stripe1Filename, stripe1errno, + RaidFileException, OSError); + } + + if(stripe2errno != 0) + { + THROW_SYS_FILE_ERRNO("Failed to stat RaidFile", + stripe2Filename, stripe2errno, + RaidFileException, OSError); + } + +>>>>>>> 0.12 // Make a nice object to represent this file return std::auto_ptr<RaidFileRead>(new RaidFileRead_Raid(SetNumber, Filename, stripe1, stripe2, -1, length, rdiscSet.GetBlockSize(), false /* actually we don't know */)); } @@ -1238,17 +1283,40 @@ std::auto_ptr<RaidFileRead> RaidFileRead::Open(int SetNumber, const std::string ASSERT(sizeof(FileSizeType) == 8); // compiler bug (I think) prevents from using 0 - sizeof(FileSizeType)... if(::lseek(parity, -8 /*(0 - sizeof(FileSizeType))*/, SEEK_END) == -1) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to seek " + "in parity RaidFile", + parityFilename, + RaidFileException, OSError); +>>>>>>> 0.12 } // Read it in if(::read(parity, &parityLastData, sizeof(parityLastData)) != sizeof(parityLastData)) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) } // Set back to beginning of file if(::lseek(parity, 0, SEEK_SET) == -1) { THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to read " + "parity RaidFile", + parityFilename, + RaidFileException, OSError); + } + + // Set back to beginning of file + if(::lseek(parity, 0, SEEK_SET) == -1) + { + THROW_SYS_FILE_ERROR("Failed to seek " + "in parity RaidFile", + parityFilename, + RaidFileException, OSError); +>>>>>>> 0.12 } } @@ -1271,7 +1339,14 @@ std::auto_ptr<RaidFileRead> RaidFileRead::Open(int SetNumber, const std::string // to get the size from the FileSizeType value at end of the file. if(::fstat(stripe1, &st) != 0) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to " + "stat RaidFile stripe 1", + stripe1Filename, + RaidFileException, OSError); +>>>>>>> 0.12 } pos_type stripe1Size = st.st_size; // Is size integral? @@ -1305,17 +1380,38 @@ std::auto_ptr<RaidFileRead> RaidFileRead::Open(int SetNumber, const std::string ASSERT(btr <= (int)sizeof(FileSizeType)); if(::lseek(stripe1, 0 - btr, SEEK_END) == -1) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to " + "seek in RaidFile stripe 1", + stripe1Filename, + RaidFileException, OSError); +>>>>>>> 0.12 } // Read it in if(::read(stripe1, &stripe1LastData, btr) != btr) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to " + "read RaidFile stripe 1", + stripe1Filename, + RaidFileException, OSError); +>>>>>>> 0.12 } // Set back to beginning of file if(::lseek(stripe1, 0, SEEK_SET) == -1) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to " + "seek in RaidFile stripe 1", + stripe1Filename, + RaidFileException, OSError); +>>>>>>> 0.12 } } // Lovely! @@ -1337,7 +1433,14 @@ std::auto_ptr<RaidFileRead> RaidFileRead::Open(int SetNumber, const std::string // Get size of stripe2 file if(::fstat(stripe2, &st) != 0) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to " + "stat RaidFile stripe 2", + stripe2Filename, + RaidFileException, OSError); +>>>>>>> 0.12 } pos_type stripe2Size = st.st_size; @@ -1406,7 +1509,12 @@ std::auto_ptr<RaidFileRead> RaidFileRead::Open(int SetNumber, const std::string } } +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, FileIsDamagedNotRecoverable) +======= + THROW_FILE_ERROR("Failed to recover RaidFile", Filename, + RaidFileException, FileIsDamagedNotRecoverable); +>>>>>>> 0.12 // Avoid compiler warning -- it'll never get here... return std::auto_ptr<RaidFileRead>(); @@ -1540,7 +1648,11 @@ bool RaidFileRead::ReadDirectoryContents(int SetNumber, const std::string &rDirN { // build name std::string dn(rdiscSet[l] + DIRECTORY_SEPARATOR + rDirName); +<<<<<<< HEAD +======= + +>>>>>>> 0.12 // read the contents... DIR *dirHandle = 0; try diff --git a/lib/raidfile/RaidFileWrite.cpp b/lib/raidfile/RaidFileWrite.cpp index f24c2422..cb1f9699 100644 --- a/lib/raidfile/RaidFileWrite.cpp +++ b/lib/raidfile/RaidFileWrite.cpp @@ -11,10 +11,24 @@ #include <errno.h> #include <fcntl.h> +<<<<<<< HEAD #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <sys/file.h> +======= + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#include <sys/types.h> +#include <sys/stat.h> + +#ifdef HAVE_SYS_FILE_H +# include <sys/file.h> +#endif +>>>>>>> 0.12 #include <stdio.h> #include <string.h> @@ -95,7 +109,32 @@ RaidFileWrite::~RaidFileWrite() { if(mOSFileHandle != -1) { +<<<<<<< HEAD Discard(); +======= + // We must not throw exceptions from the destructor + // http://stackoverflow.com/a/130123 + try + { + Discard(); + } + catch(BoxException &e) + { + BOX_ERROR("Failed to discard RaidFile update " + "in destructor: " << e.what() << " (" << + e.GetType() << "/" << e.GetSubType() << ")"); + } + catch(std::exception &e) + { + BOX_ERROR("Failed to discard RaidFile update " + "in destructor: " << e.what()); + } + catch(...) + { + BOX_ERROR("Failed to discard RaidFile update " + "in destructor: unknown exception"); + } +>>>>>>> 0.12 } } @@ -126,25 +165,45 @@ void RaidFileWrite::Open(bool AllowOverwrite) RaidFileUtil::ExistType existance = RaidFileUtil::RaidFileExists(rdiscSet, mFilename); if(existance != RaidFileUtil::NoFile) { +<<<<<<< HEAD BOX_ERROR("Attempted to overwrite raidfile " << mSetNumber << " " << mFilename); THROW_EXCEPTION(RaidFileException, CannotOverwriteExistingFile) +======= + THROW_FILE_ERROR("Attempted to overwrite raidfile " << + mSetNumber, mFilename, RaidFileException, + CannotOverwriteExistingFile); +>>>>>>> 0.12 } } // Get the filename for the write file +<<<<<<< HEAD std::string writeFilename(RaidFileUtil::MakeWriteFileName(rdiscSet, mFilename)); // Add on a temporary extension writeFilename += 'X'; // Attempt to open mOSFileHandle = ::open(writeFilename.c_str(), +======= + mTempFilename = RaidFileUtil::MakeWriteFileName(rdiscSet, mFilename); + // Add on a temporary extension + mTempFilename += 'X'; + + // Attempt to open + mOSFileHandle = ::open(mTempFilename.c_str(), +>>>>>>> 0.12 O_WRONLY | O_CREAT | O_BINARY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); if(mOSFileHandle == -1) { +<<<<<<< HEAD BOX_LOG_SYS_ERROR("Failed to open file: " << writeFilename); THROW_EXCEPTION(RaidFileException, ErrorOpeningWriteFile) +======= + THROW_SYS_FILE_ERROR("Failed to open RaidFile", mTempFilename, + RaidFileException, ErrorOpeningWriteFile); +>>>>>>> 0.12 } // Get a lock on the write file @@ -164,6 +223,7 @@ void RaidFileWrite::Open(bool AllowOverwrite) if (0) #endif { +<<<<<<< HEAD // Lock was not obtained. bool wasLocked = (errno == errnoBlock); // Close the file @@ -173,18 +233,54 @@ void RaidFileWrite::Open(bool AllowOverwrite) if(wasLocked) { THROW_EXCEPTION(RaidFileException, FileIsCurrentlyOpenForWriting) +======= + int errnoSaved = errno; + + // Lock was not obtained. + bool wasLocked = (errno == errnoBlock); + + // Close the file + ::close(mOSFileHandle); + mOSFileHandle = -1; + + // Report an exception? + if(wasLocked) + { + THROW_SYS_FILE_ERRNO("Failed to lock RaidFile, " + "already locked", mTempFilename, errnoSaved, + RaidFileException, + FileIsCurrentlyOpenForWriting); +>>>>>>> 0.12 } else { // Random error occured +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERRNO("Failed to lock RaidFile", + mTempFilename, errnoSaved, RaidFileException, + OSError); +>>>>>>> 0.12 } } // Truncate it to size zero if(::ftruncate(mOSFileHandle, 0) != 0) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, ErrorOpeningWriteFileOnTruncate) +======= + int errnoSaved = errno; + + // Close the file + ::close(mOSFileHandle); + mOSFileHandle = -1; + + THROW_SYS_FILE_ERRNO("Failed to truncate RaidFile", + mTempFilename, errnoSaved, RaidFileException, + ErrorOpeningWriteFileOnTruncate); +>>>>>>> 0.12 } // Done! @@ -210,9 +306,16 @@ void RaidFileWrite::Write(const void *pBuffer, int Length) int written = ::write(mOSFileHandle, pBuffer, Length); if(written != Length) { +<<<<<<< HEAD BOX_LOG_SYS_ERROR("RaidFileWrite failed, Length = " << Length << ", written = " << written); THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to write to RaidFile (attempted " + "to write " << Length << " bytes but managed only " << + written << ")", mTempFilename, RaidFileException, + OSError); +>>>>>>> 0.12 } } @@ -236,7 +339,12 @@ IOStream::pos_type RaidFileWrite::GetPosition() const off_t p = ::lseek(mOSFileHandle, 0, SEEK_CUR); if(p == -1) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to get position in RaidFile", + mTempFilename, RaidFileException, OSError); +>>>>>>> 0.12 } return p; @@ -261,7 +369,12 @@ void RaidFileWrite::Seek(IOStream::pos_type SeekTo, int SeekType) // Seek... if(::lseek(mOSFileHandle, SeekTo, ConvertSeekTypeToOSWhence(SeekType)) == -1) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to set position in RaidFile", + mTempFilename, RaidFileException, OSError); +>>>>>>> 0.12 } } @@ -283,9 +396,14 @@ void RaidFileWrite::Commit(bool ConvertToRaidNow) if (mRefCount == 0) { +<<<<<<< HEAD BOX_ERROR("Attempted to modify object " << mFilename << ", which has no references"); THROW_EXCEPTION(RaidFileException, +======= + THROW_FILE_ERROR("Attempted to modify object file with " + "no references", mTempFilename, RaidFileException, +>>>>>>> 0.12 RequestedModifyUnreferencedFile); } @@ -296,7 +414,12 @@ void RaidFileWrite::Commit(bool ConvertToRaidNow) // Close file... if(::close(mOSFileHandle) != 0) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_WIN_FILE_ERROR("Failed to close RaidFile for rename", + mTempFilename, RaidFileException, OSError); +>>>>>>> 0.12 } mOSFileHandle = -1; #endif // WIN32 @@ -310,26 +433,47 @@ void RaidFileWrite::Commit(bool ConvertToRaidNow) #ifdef WIN32 // need to delete the target first +<<<<<<< HEAD if(::unlink(renameTo.c_str()) != 0 && GetLastError() != ERROR_FILE_NOT_FOUND) { BOX_LOG_WIN_ERROR("Failed to delete file: " << renameTo); THROW_EXCEPTION(RaidFileException, OSError) +======= + if(::unlink(renameTo.c_str()) != 0) + { + DWORD errorNumber = GetLastError(); + if (errorNumber != ERROR_FILE_NOT_FOUND) + { + THROW_WIN_FILE_ERRNO("Failed to delete file", renameTo, + errorNumber, RaidFileException, OSError); + } +>>>>>>> 0.12 } #endif if(::rename(renameFrom.c_str(), renameTo.c_str()) != 0) { +<<<<<<< HEAD BOX_LOG_SYS_ERROR("Failed to rename file: " << renameFrom << " to " << renameTo); THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_ERROR("Failed to rename file: " << renameFrom << + " to " << renameTo, RaidFileException, OSError); +>>>>>>> 0.12 } #ifndef WIN32 // Close file... if(::close(mOSFileHandle) != 0) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to close committed RaidFile", + mTempFilename, RaidFileException, OSError); +>>>>>>> 0.12 } mOSFileHandle = -1; #endif // !WIN32 @@ -376,8 +520,13 @@ void RaidFileWrite::Discard() ::close(mOSFileHandle) != 0) #endif // !WIN32 { +<<<<<<< HEAD BOX_LOG_SYS_ERROR("Failed to delete file: " << writeFilename); THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to delete file", writeFilename, + RaidFileException, OSError); +>>>>>>> 0.12 } // reset file handle @@ -678,10 +827,16 @@ void RaidFileWrite::Delete() { if (mRefCount != 0 && mRefCount != -1) { +<<<<<<< HEAD BOX_ERROR("Attempted to delete object " << mFilename << " which has " << mRefCount << " references"); THROW_EXCEPTION(RaidFileException, RequestedDeleteReferencedFile); +======= + THROW_FILE_ERROR("Attempted to delete object with " << + mRefCount << " references", mFilename, + RaidFileException, RequestedDeleteReferencedFile); +>>>>>>> 0.12 } // Get disc set @@ -692,7 +847,13 @@ void RaidFileWrite::Delete() RaidFileUtil::ExistType existance = RaidFileUtil::RaidFileExists(rdiscSet, mFilename); if(existance == RaidFileUtil::NoFile) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, RaidFileDoesntExist) +======= + THROW_FILE_ERROR("Attempted to delete object which doesn't " + "exist", mFilename, RaidFileException, + RaidFileDoesntExist); +>>>>>>> 0.12 } // Get the filename for the write file @@ -731,7 +892,12 @@ void RaidFileWrite::Delete() // Check something happened if(!deletedSomething) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_FILE_ERROR("Failed to delete a RaidFile stripe set", + mFilename, RaidFileException, OSError); +>>>>>>> 0.12 } } @@ -802,11 +968,24 @@ void RaidFileWrite::CreateDirectory(const RaidFileDiscSet &rSet, const std::stri if(errno == EEXIST) { // No. Bad things. +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, FileExistsInDirectoryCreation) } else { THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to create " + "RaidFile directory", dn, + RaidFileException, + FileExistsInDirectoryCreation); + } + else + { + THROW_SYS_FILE_ERROR("Failed to create " + "RaidFile directory", dn, + RaidFileException, OSError); +>>>>>>> 0.12 } } } @@ -889,7 +1068,12 @@ IOStream::pos_type RaidFileWrite::GetFileSize() struct stat st; if(fstat(mOSFileHandle, &st) != 0) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to stat RaidFile", mTempFilename, + RaidFileException, OSError); +>>>>>>> 0.12 } return st.st_size; @@ -918,7 +1102,12 @@ IOStream::pos_type RaidFileWrite::GetDiscUsageInBlocks() struct stat st; if(fstat(mOSFileHandle, &st) != 0) { +<<<<<<< HEAD THROW_EXCEPTION(RaidFileException, OSError) +======= + THROW_SYS_FILE_ERROR("Failed to stat RaidFile", mTempFilename, + RaidFileException, OSError); +>>>>>>> 0.12 } // Then return calculation diff --git a/lib/raidfile/RaidFileWrite.h b/lib/raidfile/RaidFileWrite.h index 418f90ee..52621676 100644 --- a/lib/raidfile/RaidFileWrite.h +++ b/lib/raidfile/RaidFileWrite.h @@ -27,7 +27,22 @@ class RaidFileDiscSet; class RaidFileWrite : public IOStream { public: +<<<<<<< HEAD RaidFileWrite(int SetNumber, const std::string &Filename); +======= + // TODO FIXME we should remove this constructor, and ensure that + // anyone who writes to a RaidFile knows what the reference count + // is before doing so. That requires supporting regenerating the + // reference count database in BackupStoreCheck, and using a real + // database instead of an in-memory array in HousekeepStoreAccount, + // and supporting multiple databases at a time (old and new) in + // BackupStoreRefCountDatabase, and I don't have time to make those + // changes right now. We may even absolutely need to have a full + // reference database, not just reference counts, to implement + // snapshots. + RaidFileWrite(int SetNumber, const std::string &Filename); + +>>>>>>> 0.12 RaidFileWrite(int SetNumber, const std::string &Filename, int refcount); ~RaidFileWrite(); private: @@ -59,7 +74,11 @@ private: private: int mSetNumber; +<<<<<<< HEAD std::string mFilename; +======= + std::string mFilename, mTempFilename; +>>>>>>> 0.12 int mOSFileHandle; int mRefCount; }; |