[Box Backup-commit] COMMIT r2543 - in box/trunk: lib/raidfile test/raidfile

boxbackup-dev@boxbackup.org boxbackup-dev@boxbackup.org
Sun, 5 Jul 2009 22:43:57 +0100 (BST)


Author: chris
Date: 2009-07-05 22:43:57 +0100 (Sun, 05 Jul 2009)
New Revision: 2543

Modified:
   box/trunk/lib/raidfile/RaidFileException.txt
   box/trunk/lib/raidfile/RaidFileWrite.cpp
   box/trunk/lib/raidfile/RaidFileWrite.h
   box/trunk/test/raidfile/testraidfile.cpp
Log:
Allow RaidFileWrite to test that the reference count of an object is 
correct before overwriting or deleting it.


Modified: box/trunk/lib/raidfile/RaidFileException.txt
===================================================================
--- box/trunk/lib/raidfile/RaidFileException.txt	2009-06-28 19:33:34 UTC (rev 2542)
+++ box/trunk/lib/raidfile/RaidFileException.txt	2009-07-05 21:43:57 UTC (rev 2543)
@@ -23,3 +23,6 @@
 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.

Modified: box/trunk/lib/raidfile/RaidFileWrite.cpp
===================================================================
--- box/trunk/lib/raidfile/RaidFileWrite.cpp	2009-06-28 19:33:34 UTC (rev 2542)
+++ box/trunk/lib/raidfile/RaidFileWrite.cpp	2009-07-05 21:43:57 UTC (rev 2543)
@@ -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 @@
 	{
 		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::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));

Modified: box/trunk/lib/raidfile/RaidFileWrite.h
===================================================================
--- box/trunk/lib/raidfile/RaidFileWrite.h	2009-06-28 19:33:34 UTC (rev 2542)
+++ box/trunk/lib/raidfile/RaidFileWrite.h	2009-07-05 21:43:57 UTC (rev 2543)
@@ -28,6 +28,7 @@
 {
 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 @@
 	int mSetNumber;
 	std::string mFilename;
 	int mOSFileHandle;
+	int mRefCount;
 };
 
 #endif // RAIDFILEWRITE__H

Modified: box/trunk/test/raidfile/testraidfile.cpp
===================================================================
--- box/trunk/test/raidfile/testraidfile.cpp	2009-06-28 19:33:34 UTC (rev 2542)
+++ box/trunk/test/raidfile/testraidfile.cpp	2009-07-05 21:43:57 UTC (rev 2543)
@@ -627,6 +627,30 @@
 			"', '" << 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