diff options
-rw-r--r-- | lib/raidfile/RaidFileException.txt | 3 | ||||
-rw-r--r-- | lib/raidfile/RaidFileWrite.cpp | 52 | ||||
-rw-r--r-- | lib/raidfile/RaidFileWrite.h | 2 | ||||
-rw-r--r-- | test/raidfile/testraidfile.cpp | 24 |
4 files changed, 78 insertions, 3 deletions
diff --git a/lib/raidfile/RaidFileException.txt b/lib/raidfile/RaidFileException.txt index c69dc2a2..c7ddfcc5 100644 --- a/lib/raidfile/RaidFileException.txt +++ b/lib/raidfile/RaidFileException.txt @@ -23,3 +23,6 @@ CanOnlyGetUsageBeforeCommit 19 CanOnlyGetFileSizeBeforeCommit 20 ErrorOpeningWriteFileOnTruncate 21 FileIsCurrentlyOpenForWriting 22 +RequestedModifyUnreferencedFile 23 Internal error: the server attempted to modify a file which has no references. +RequestedModifyMultiplyReferencedFile 24 Internal error: the server attempted to modify a file which has multiple references. +RequestedDeleteReferencedFile 25 Internal error: the server attempted to delete a file which is still referenced. diff --git a/lib/raidfile/RaidFileWrite.cpp b/lib/raidfile/RaidFileWrite.cpp index 00067f72..2d852f86 100644 --- a/lib/raidfile/RaidFileWrite.cpp +++ b/lib/raidfile/RaidFileWrite.cpp @@ -42,20 +42,50 @@ // // Function // Name: RaidFileWrite::RaidFileWrite(int, const std::string &) -// Purpose: Construtor, just stores requried details +// Purpose: Simple constructor, just stores required details // Created: 2003/07/10 // // -------------------------------------------------------------------------- RaidFileWrite::RaidFileWrite(int SetNumber, const std::string &Filename) : mSetNumber(SetNumber), mFilename(Filename), - mOSFileHandle(-1) // not valid file handle + mOSFileHandle(-1), // not valid file handle + mRefCount(-1) // unknown refcount { } // -------------------------------------------------------------------------- // // Function +// Name: RaidFileWrite::RaidFileWrite(int, +// const std::string &, int refcount) +// Purpose: Constructor with check for overwriting file +// with multiple references +// Created: 2009/07/05 +// +// -------------------------------------------------------------------------- +RaidFileWrite::RaidFileWrite(int SetNumber, const std::string &Filename, + int refcount) + : mSetNumber(SetNumber), + mFilename(Filename), + mOSFileHandle(-1), // not valid file handle + mRefCount(refcount) +{ + // Can't check for zero refcount here, because it's legal + // to create a RaidFileWrite to delete an object with zero refcount. + // Check in Commit() and Delete() instead. + if (refcount > 1) + { + BOX_ERROR("Attempted to modify object " << mFilename << + ", which has " << refcount << " references"); + THROW_EXCEPTION(RaidFileException, + RequestedModifyMultiplyReferencedFile); + } +} + +// -------------------------------------------------------------------------- +// +// Function // Name: RaidFileWrite::~RaidFileWrite() // Purpose: Destructor (will discard written file if not commited) // Created: 2003/07/10 @@ -250,7 +280,15 @@ void RaidFileWrite::Commit(bool ConvertToRaidNow) { THROW_EXCEPTION(RaidFileException, NotOpen) } - + + if (mRefCount == 0) + { + BOX_ERROR("Attempted to modify object " << mFilename << + ", which has no references"); + THROW_EXCEPTION(RaidFileException, + RequestedModifyUnreferencedFile); + } + // Rename it into place -- BEFORE it's closed so lock remains #ifdef WIN32 @@ -638,6 +676,14 @@ void RaidFileWrite::TransformToRaidStorage() // -------------------------------------------------------------------------- void RaidFileWrite::Delete() { + if (mRefCount != 0 && mRefCount != -1) + { + BOX_ERROR("Attempted to delete object " << mFilename << + " which has " << mRefCount << " references"); + THROW_EXCEPTION(RaidFileException, + RequestedDeleteReferencedFile); + } + // Get disc set RaidFileController &rcontroller(RaidFileController::GetController()); RaidFileDiscSet rdiscSet(rcontroller.GetDiscSet(mSetNumber)); diff --git a/lib/raidfile/RaidFileWrite.h b/lib/raidfile/RaidFileWrite.h index d7e51f21..418f90ee 100644 --- a/lib/raidfile/RaidFileWrite.h +++ b/lib/raidfile/RaidFileWrite.h @@ -28,6 +28,7 @@ class RaidFileWrite : public IOStream { public: RaidFileWrite(int SetNumber, const std::string &Filename); + RaidFileWrite(int SetNumber, const std::string &Filename, int refcount); ~RaidFileWrite(); private: RaidFileWrite(const RaidFileWrite &rToCopy); @@ -60,6 +61,7 @@ private: int mSetNumber; std::string mFilename; int mOSFileHandle; + int mRefCount; }; #endif // RAIDFILEWRITE__H diff --git a/test/raidfile/testraidfile.cpp b/test/raidfile/testraidfile.cpp index 530fb7f8..160de5c9 100644 --- a/test/raidfile/testraidfile.cpp +++ b/test/raidfile/testraidfile.cpp @@ -627,6 +627,30 @@ int test(int argc, const char *argv[]) "', '" << n3); } + // Test that creating and deleting a RaidFile with the wrong + // reference counts throws the expected errors. + { + RaidFileWrite write1(0, "write1", 1); + write1.Open(); + write1.Commit(); + TEST_CHECK_THROWS(write1.Delete(), RaidFileException, + RequestedDeleteReferencedFile); + } + + { + RaidFileWrite write1(0, "write1", 0); + write1.Open(true); + TEST_CHECK_THROWS(write1.Commit(), RaidFileException, + RequestedModifyUnreferencedFile); + write1.Delete(); + } + + { + TEST_CHECK_THROWS(RaidFileWrite write1(0, "write1", 2), + RaidFileException, + RequestedModifyMultiplyReferencedFile); + } + // Create a RaidFile RaidFileWrite write1(0, "test1"); IOStream &write1stream = write1; // use the stream interface where possible |