[Box Backup-commit] COMMIT r1603 - in box/chris/general: bin/bbackupd bin/bbackupquery lib/backupclient lib/common lib/server test/bbackupd test/common

boxbackup-dev@fluffy.co.uk boxbackup-dev@fluffy.co.uk
Sat, 28 Apr 2007 22:19:34 +0100


Author: chris
Date: 2007-04-28 22:19:34 +0100 (Sat, 28 Apr 2007)
New Revision: 1603

Added:
   box/chris/general/lib/common/ReadLoggingStream.cpp
   box/chris/general/lib/common/ReadLoggingStream.h
Modified:
   box/chris/general/bin/bbackupd/BackupClientDirectoryRecord.cpp
   box/chris/general/bin/bbackupd/BackupDaemon.cpp
   box/chris/general/bin/bbackupd/BackupDaemon.h
   box/chris/general/bin/bbackupquery/BackupQueries.cpp
   box/chris/general/bin/bbackupquery/bbackupquery.cpp
   box/chris/general/lib/backupclient/BackupStoreFile.cpp
   box/chris/general/lib/backupclient/BackupStoreFileEncodeStream.cpp
   box/chris/general/lib/backupclient/BackupStoreFileEncodeStream.h
   box/chris/general/lib/common/BannerText.h
   box/chris/general/lib/common/Logging.cpp
   box/chris/general/lib/common/Logging.h
   box/chris/general/lib/common/PartialReadStream.cpp
   box/chris/general/lib/common/PartialReadStream.h
   box/chris/general/lib/common/ReadGatherStream.cpp
   box/chris/general/lib/server/Daemon.cpp
   box/chris/general/lib/server/Daemon.h
   box/chris/general/lib/server/ServerStream.h
   box/chris/general/test/bbackupd/testbbackupd.cpp
   box/chris/general/test/common/testcommon.cpp
Log:
Merged changes from chris/merge, revisions 1585 to 1602:

 * [1585] Add a stream which provides a source of zero bytes of arbitrary
   size, useful for testing support for files over 2GB.
 * [1586] Fix inability to handle streams over 2GB properly in GetObject.
 * [1587] Test that PartialReadStream and ReadGatherStream can handle
   streams over 2GB in size.
 * [1588] In logging framework, keep a copy of the program name, in case
   the original goes away, which causes syslog() to write nonsense for
   the program name (not relevant to Win32, merging only).
 * [1589] Add a stream which logs progress of reading data from another
   (child) stream, and estimated time of completion, useful for upload
   progress monitoring.
 * [1590] Use ReadLoggingStream to log progress of file uploads.
 * [1591] Make Daemon remember whether we're supposed to run in a single
   process, or not (cosmetic only on Win32).
 * [1593] Don't fork to handle requests when running as a single process
   (cosmetic only on Win32).
 * [1594] Improve log message for NotifyFileUploading().
 * [1595] Notify about full file uploads.
 * [1596] Fix formatting bugs.
 * [1597] Improve error messages in bbackupquery when getting a file
   fails with an exception.
 * [1598] Fix getting files with uncertain size (over 2GB) from the store.
 * [1599] Fix bbackupd choosing an invalid (too large) block size for
   large files (over 2GB) which will cause compare to fail.
 * [1600] Improve error messages in bbackupquery when compare throws an
   exception.
 * [1601] Remove newline from end of banner text, since logging framework
   will add it for us where necessary.
 * [1602] Use logging framework for banner in bbackupquery.


Modified: box/chris/general/bin/bbackupd/BackupClientDirectoryRecord.cpp
===================================================================
--- box/chris/general/bin/bbackupd/BackupClientDirectoryRecord.cpp	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/bin/bbackupd/BackupClientDirectoryRecord.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -31,6 +31,7 @@
 #include "Archive.h"
 #include "PathUtils.h"
 #include "Logging.h"
+#include "ReadLoggingStream.h"
 
 #include "MemLeakFindOn.h"
 
@@ -1357,9 +1358,13 @@
 		if(doNormalUpload)
 		{
 			// below threshold or nothing to diff from, so upload whole
+			rParams.GetProgressNotifier().NotifyFileUploading(this, 
+				rFilename);
 			
 			// Prepare to upload, getting a stream which will encode the file as we go along
-			std::auto_ptr<IOStream> upload(BackupStoreFile::EncodeFile(rFilename.c_str(), mObjectID, rStoreFilename));
+			std::auto_ptr<IOStream> upload(
+				BackupStoreFile::EncodeFile(rFilename.c_str(),
+					mObjectID, rStoreFilename));
 		
 			// Send to store
 			std::auto_ptr<BackupProtocolClientSuccess> stored(

Modified: box/chris/general/bin/bbackupd/BackupDaemon.cpp
===================================================================
--- box/chris/general/bin/bbackupd/BackupDaemon.cpp	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/bin/bbackupd/BackupDaemon.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -300,14 +300,14 @@
 		}
 		catch (BoxException &e)
 		{
-			BOX_ERROR("Failed to open command socket" << 
+			BOX_ERROR("Failed to open command socket: " << 
 				e.what());
 			SetTerminateWanted();
 			break; // this is fatal to listening thread
 		}
 		catch(std::exception &e)
 		{
-			BOX_ERROR("Failed to open command socket" <<
+			BOX_ERROR("Failed to open command socket: " <<
 				e.what());
 			SetTerminateWanted();
 			break; // this is fatal to listening thread

Modified: box/chris/general/bin/bbackupd/BackupDaemon.h
===================================================================
--- box/chris/general/bin/bbackupd/BackupDaemon.h	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/bin/bbackupd/BackupDaemon.h	2007-04-28 21:19:34 UTC (rev 1603)
@@ -308,7 +308,7 @@
 	{ 
 		if (mLogAllFileAccess)
 		{
-			BOX_INFO("Uploading file: " << rLocalPath);
+			BOX_INFO("Uploading complete file: " << rLocalPath);
 		} 
 	}
  	virtual void NotifyFileUploadingPatch(

Modified: box/chris/general/bin/bbackupquery/BackupQueries.cpp
===================================================================
--- box/chris/general/bin/bbackupquery/BackupQueries.cpp	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/bin/bbackupquery/BackupQueries.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -47,6 +47,7 @@
 #include "ExcludeList.h"
 #include "BackupClientMakeExcludeList.h"
 #include "PathUtils.h"
+#include "Logging.h"
 
 #include "MemLeakFindOn.h"
 
@@ -1047,10 +1048,22 @@
 		// Done.
 		printf("Object ID %08llx fetched sucessfully.\n", fileId);
 	}
+	catch (BoxException &e)
+	{
+		BOX_ERROR("Failed to fetch file: " << 
+			e.what());
+		::unlink(localName.c_str());
+	}
+	catch(std::exception &e)
+	{
+		BOX_ERROR("Failed to fetch file: " <<
+			e.what());
+		::unlink(localName.c_str());
+	}
 	catch(...)
 	{
+		BOX_ERROR("Failed to fetch file: unknown error");
 		::unlink(localName.c_str());
-		printf("Error occured fetching file.\n");
 	}
 }
 
@@ -1717,15 +1730,27 @@
 				}
 				catch(BoxException &e)
 				{
-					printf("ERROR: (%d/%d) during file fetch and comparison for '%s'\n",
-						e.GetType(),
-						e.GetSubType(),
-						storePathDisplay.c_str());
+					BOX_ERROR("Failed to fetch and compare "
+						"'" << 
+						storePathDisplay.c_str() <<
+						"': error " << e.what() <<
+						" (" << e.GetType() <<
+						"/"  << e.GetSubType() << ")");
 					rParams.mUncheckedFiles ++;
 				}
+				catch(std::exception &e)
+				{
+					BOX_ERROR("Failed to fetch and compare "
+						"'" << 
+						storePathDisplay.c_str() <<
+						"': " << e.what());
+				}
 				catch(...)
 				{	
-					printf("ERROR: (unknown) during file fetch and comparison for '%s'\n", storePathDisplay.c_str());
+					BOX_ERROR("Failed to fetch and compare "
+						"'" << 
+						storePathDisplay.c_str() <<
+						"': unknown error");
 					rParams.mUncheckedFiles ++;
 				}
 

Modified: box/chris/general/bin/bbackupquery/bbackupquery.cpp
===================================================================
--- box/chris/general/bin/bbackupquery/bbackupquery.cpp	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/bin/bbackupquery/bbackupquery.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -186,7 +186,7 @@
 	if(!quiet)
 	{
 		const char *banner = BANNER_TEXT("Backup Query Tool");
-		printf(banner);
+		BOX_NOTICE(banner);
 	}
 
 #ifdef WIN32

Modified: box/chris/general/lib/backupclient/BackupStoreFile.cpp
===================================================================
--- box/chris/general/lib/backupclient/BackupStoreFile.cpp	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/lib/backupclient/BackupStoreFile.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -292,6 +292,14 @@
 		}
 
 		out.Close();
+
+		// The stream might have uncertain size, in which case
+		// we need to drain it to get the 
+		// Protocol::ProtocolStreamHeader_EndOfStream byte
+		// out of our connection stream.
+		char buffer[1];
+		int drained = rEncodedFile.Read(buffer, 1);
+		ASSERT(drained == 0);
 		
 		// Write the attributes
 		stream->GetAttributes().WriteAttributes(DecodedFilename);

Modified: box/chris/general/lib/backupclient/BackupStoreFileEncodeStream.cpp
===================================================================
--- box/chris/general/lib/backupclient/BackupStoreFileEncodeStream.cpp	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/lib/backupclient/BackupStoreFileEncodeStream.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -38,6 +38,7 @@
 BackupStoreFileEncodeStream::BackupStoreFileEncodeStream()
 	: mpRecipe(0),
 	  mpFile(0),
+	  mpLogging(0),
 	  mStatus(Status_Header),
 	  mSendData(true),
 	  mTotalBlocks(0),
@@ -79,6 +80,13 @@
 		mpFile = 0;
 	}
 	
+	// Clear up logging stream
+	if(mpLogging)
+	{
+		delete mpLogging;
+		mpLogging = 0;
+	}
+	
 	// Free the recipe
 	if(mpRecipe != 0)
 	{
@@ -199,6 +207,9 @@
 		{
 			// Open the file
 			mpFile = new FileStream(Filename);
+
+			// Create logging stream
+			mpLogging = new ReadLoggingStream(*mpFile);
 		
 			// Work out the largest possible block required for the encoded data
 			mAllocatedBufferSize = BackupStoreFile::MaxBlockSizeForChunkSize(maxBlockClearSize);
@@ -267,7 +278,7 @@
 		
 		rNumBlocksOut = (DataSize + rBlockSizeOut - 1) / rBlockSizeOut;
 		
-	} while(rBlockSizeOut <= BACKUP_FILE_MAX_BLOCK_SIZE && rNumBlocksOut > BACKUP_FILE_INCREASE_BLOCK_SIZE_AFTER);
+	} while(rBlockSizeOut < BACKUP_FILE_MAX_BLOCK_SIZE && rNumBlocksOut > BACKUP_FILE_INCREASE_BLOCK_SIZE_AFTER);
 	
 	// Last block size
 	rLastBlockSizeOut = DataSize - ((rNumBlocksOut - 1) * rBlockSizeOut);
@@ -474,7 +485,7 @@
 	}
 	
 	// Move forward in the stream
-	mpFile->Seek(sizeToSkip, IOStream::SeekType_Relative);
+	mpLogging->Seek(sizeToSkip, IOStream::SeekType_Relative);
 }
 
 
@@ -518,14 +529,14 @@
 	ASSERT(blockRawSize < mAllocatedBufferSize);
 
 	// Check file open
-	if(mpFile == 0)
+	if(mpFile == 0 || mpLogging == 0)
 	{
 		// File should be open, but isn't. So logical error.
 		THROW_EXCEPTION(BackupStoreException, Internal)
 	}
 	
 	// Read the data in
-	if(!mpFile->ReadFullBuffer(mpRawBuffer, blockRawSize, 0 /* not interested in size if failure */))
+	if(!mpLogging->ReadFullBuffer(mpRawBuffer, blockRawSize, 0 /* not interested in size if failure */))
 	{
 		// TODO: Do something more intelligent, and abort this upload because the file
 		// has changed

Modified: box/chris/general/lib/backupclient/BackupStoreFileEncodeStream.h
===================================================================
--- box/chris/general/lib/backupclient/BackupStoreFileEncodeStream.h	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/lib/backupclient/BackupStoreFileEncodeStream.h	2007-04-28 21:19:34 UTC (rev 1603)
@@ -17,6 +17,7 @@
 #include "CollectInBufferStream.h"
 #include "MD5Digest.h"
 #include "BackupStoreFile.h"
+#include "ReadLoggingStream.h"
 
 namespace BackupStoreFileCreation
 {
@@ -100,6 +101,7 @@
 	Recipe *mpRecipe;
 	IOStream *mpFile;					// source file
 	CollectInBufferStream mData;		// buffer for header and index entries
+	ReadLoggingStream *mpLogging;
 	int mStatus;
 	bool mSendData;						// true if there's file data to send (ie not a symlink)
 	int64_t mTotalBlocks;				// Total number of blocks in the file

Modified: box/chris/general/lib/common/BannerText.h
===================================================================
--- box/chris/general/lib/common/BannerText.h	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/lib/common/BannerText.h	2007-04-28 21:19:34 UTC (rev 1603)
@@ -11,7 +11,7 @@
 #define BANNERTEXT__H
 
 #define BANNER_TEXT(UtilityName) \
-	"Box " UtilityName " v" BOX_VERSION ", (c) Ben Summers and contributors 2003-2006\n"
+	"Box " UtilityName " v" BOX_VERSION ", (c) Ben Summers and contributors 2003-2006"
 
 #endif // BANNERTEXT__H
 

Modified: box/chris/general/lib/common/Logging.cpp
===================================================================
--- box/chris/general/lib/common/Logging.cpp	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/lib/common/Logging.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -289,6 +289,7 @@
 
 void Syslog::SetProgramName(const std::string& rProgramName)
 {
+	mName = rProgramName;
 	::closelog();
-	::openlog(rProgramName.c_str(), LOG_PID, LOG_LOCAL6);
+	::openlog(mName.c_str(), LOG_PID, LOG_LOCAL6);
 }

Modified: box/chris/general/lib/common/Logging.h
===================================================================
--- box/chris/general/lib/common/Logging.h	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/lib/common/Logging.h	2007-04-28 21:19:34 UTC (rev 1603)
@@ -128,6 +128,9 @@
 
 class Syslog : public Logger
 {
+	private:
+	std::string mName;
+
 	public:
 	Syslog();
 	virtual ~Syslog();

Modified: box/chris/general/lib/common/PartialReadStream.cpp
===================================================================
--- box/chris/general/lib/common/PartialReadStream.cpp	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/lib/common/PartialReadStream.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -16,13 +16,15 @@
 // --------------------------------------------------------------------------
 //
 // Function
-//		Name:    PartialReadStream::PartialReadStream(IOStream &, int)
-//		Purpose: Constructor, taking another stream and the number of bytes
-//				 to be read from it.
+//		Name:    PartialReadStream::PartialReadStream(IOStream &,
+//			 pos_type)
+//		Purpose: Constructor, taking another stream and the number of
+//			 bytes to be read from it.
 //		Created: 2003/08/26
 //
 // --------------------------------------------------------------------------
-PartialReadStream::PartialReadStream(IOStream &rSource, int BytesToRead)
+PartialReadStream::PartialReadStream(IOStream &rSource,
+	pos_type BytesToRead)
 	: mrSource(rSource),
 	  mBytesLeft(BytesToRead)
 {

Modified: box/chris/general/lib/common/PartialReadStream.h
===================================================================
--- box/chris/general/lib/common/PartialReadStream.h	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/lib/common/PartialReadStream.h	2007-04-28 21:19:34 UTC (rev 1603)
@@ -23,7 +23,7 @@
 class PartialReadStream : public IOStream
 {
 public:
-	PartialReadStream(IOStream &rSource, int BytesToRead);
+	PartialReadStream(IOStream &rSource, pos_type BytesToRead);
 	~PartialReadStream();
 private:
 	// no copying allowed
@@ -39,7 +39,7 @@
 
 private:
 	IOStream &mrSource;
-	int mBytesLeft;
+	pos_type mBytesLeft;
 };
 
 #endif // PARTIALREADSTREAM__H

Modified: box/chris/general/lib/common/ReadGatherStream.cpp
===================================================================
--- box/chris/general/lib/common/ReadGatherStream.cpp	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/lib/common/ReadGatherStream.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -59,8 +59,9 @@
 //
 // Function
 //		Name:    ReadGatherStream::AddComponent(IOStream *)
-//		Purpose: Add a component to this stream, returning the index of this component
-//				 in the internal list. Use this with AddBlock()
+//		Purpose: Add a component to this stream, returning the index
+//			 of this component in the internal list. Use this
+//			 with AddBlock()
 //		Created: 10/12/03
 //
 // --------------------------------------------------------------------------
@@ -145,10 +146,10 @@
 		if(mPositionInCurrentBlock < mBlocks[mCurrentBlock].mLength)
 		{
 			// Read!
-			int s = mBlocks[mCurrentBlock].mLength - mPositionInCurrentBlock;
+			pos_type s = mBlocks[mCurrentBlock].mLength - mPositionInCurrentBlock;
 			if(s > bytesToRead) s = bytesToRead;
 			
-			int r = mComponents[mBlocks[mCurrentBlock].mComponent]->Read(buffer, s, Timeout);
+			pos_type r = mComponents[mBlocks[mCurrentBlock].mComponent]->Read(buffer, s, Timeout);
 			
 			// update variables
 			mPositionInCurrentBlock += r;

Copied: box/chris/general/lib/common/ReadLoggingStream.cpp (from rev 1602, box/chris/merge/lib/common/ReadLoggingStream.cpp)
===================================================================
--- box/chris/general/lib/common/ReadLoggingStream.cpp	                        (rev 0)
+++ box/chris/general/lib/common/ReadLoggingStream.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -0,0 +1,207 @@
+// --------------------------------------------------------------------------
+//
+// File
+//		Name:    ReadLoggingStream.cpp
+//		Purpose: Buffering wrapper around IOStreams
+//		Created: 2007/01/16
+//
+// --------------------------------------------------------------------------
+
+#include "Box.h"
+
+#include <string.h>
+
+#include "ReadLoggingStream.h"
+#include "CommonException.h"
+#include "Logging.h"
+
+#include "MemLeakFindOn.h"
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    ReadLoggingStream::ReadLoggingStream(const char *, int, int)
+//		Purpose: Constructor, set up buffer
+//		Created: 2007/01/16
+//
+// --------------------------------------------------------------------------
+ReadLoggingStream::ReadLoggingStream(IOStream& rSource)
+: mrSource(rSource),
+  mOffset(0),
+  mLength(mrSource.BytesLeftToRead()),
+  mTotalRead(0),
+  mStartTime(GetCurrentBoxTime())
+{ }
+
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    ReadLoggingStream::Read(void *, int)
+//		Purpose: Reads bytes from the file
+//		Created: 2007/01/16
+//
+// --------------------------------------------------------------------------
+int ReadLoggingStream::Read(void *pBuffer, int NBytes, int Timeout)
+{
+	int numBytesRead = mrSource.Read(pBuffer, NBytes, Timeout);
+
+	if (numBytesRead > 0)
+	{
+		mTotalRead += numBytesRead;
+		mOffset += numBytesRead;
+	}
+
+	if (mLength >= 0 && mTotalRead > 0)
+	{	
+		box_time_t timeNow = GetCurrentBoxTime();
+		box_time_t elapsed = timeNow - mStartTime;
+		box_time_t finish  = (elapsed * mLength) / mTotalRead;
+		box_time_t remain  = finish - elapsed;
+
+		BOX_TRACE("Read " << numBytesRead << " bytes at " << mOffset << 
+			", " << (mLength - mOffset) << " remain, eta " <<
+			BoxTimeToSeconds(remain) << "s");
+	}
+	else if (mLength >= 0 && mTotalRead == 0)
+	{
+		BOX_TRACE("Read " << numBytesRead << " bytes at " << mOffset << 
+			", " << (mLength - mOffset) << " remain");
+	}
+	else
+	{	
+		BOX_TRACE("Read " << numBytesRead << " bytes at " << mOffset << 
+			", unknown bytes remaining");
+	}
+	
+	return numBytesRead;
+}
+
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    ReadLoggingStream::BytesLeftToRead()
+//		Purpose: Returns number of bytes to read (may not be most efficient function ever)
+//		Created: 2007/01/16
+//
+// --------------------------------------------------------------------------
+IOStream::pos_type ReadLoggingStream::BytesLeftToRead()
+{
+	return mLength - mOffset;
+}
+
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    ReadLoggingStream::Write(void *, int)
+//		Purpose: Writes bytes to the underlying stream (not supported)
+//		Created: 2003/07/31
+//
+// --------------------------------------------------------------------------
+void ReadLoggingStream::Write(const void *pBuffer, int NBytes)
+{
+	THROW_EXCEPTION(CommonException, NotSupported);
+}
+
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    ReadLoggingStream::GetPosition()
+//		Purpose: Get position in stream
+//		Created: 2003/08/21
+//
+// --------------------------------------------------------------------------
+IOStream::pos_type ReadLoggingStream::GetPosition() const
+{
+	return mOffset;
+}
+
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    ReadLoggingStream::Seek(pos_type, int)
+//		Purpose: Seeks within file, as lseek, invalidate buffer
+//		Created: 2003/07/31
+//
+// --------------------------------------------------------------------------
+void ReadLoggingStream::Seek(IOStream::pos_type Offset, int SeekType)
+{
+	mrSource.Seek(Offset, SeekType);
+
+	switch (SeekType)
+	{
+		case SeekType_Absolute:
+		{
+			// just go there
+			mOffset = Offset;
+		}
+		break;
+
+		case SeekType_Relative:
+		{
+			// Actual underlying file position is 
+			// (mBufferSize - mBufferPosition) ahead of us.
+			// Need to subtract that amount from the seek
+			// to seek forward that much less, putting the 
+			// real pointer in the right place.
+			mOffset += Offset;
+		}
+		break;
+
+		case SeekType_End:
+		{
+			// Actual underlying file position is 
+			// (mBufferSize - mBufferPosition) ahead of us.
+			// Need to add that amount to the seek
+			// to seek backwards that much more, putting the 
+			// real pointer in the right place.
+			mOffset = mLength - Offset;
+		}
+	}
+}
+
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    ReadLoggingStream::Close()
+//		Purpose: Closes the underlying stream (not needed)
+//		Created: 2003/07/31
+//
+// --------------------------------------------------------------------------
+void ReadLoggingStream::Close()
+{
+	THROW_EXCEPTION(CommonException, NotSupported);
+}
+
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    ReadLoggingStream::StreamDataLeft()
+//		Purpose: Any data left to write?
+//		Created: 2003/08/02
+//
+// --------------------------------------------------------------------------
+bool ReadLoggingStream::StreamDataLeft()
+{
+	return mrSource.StreamDataLeft();
+}
+
+// --------------------------------------------------------------------------
+//
+// Function
+//		Name:    ReadLoggingStream::StreamClosed()
+//		Purpose: Is the stream closed?
+//		Created: 2003/08/02
+//
+// --------------------------------------------------------------------------
+bool ReadLoggingStream::StreamClosed()
+{
+	return mrSource.StreamClosed();
+}
+


Property changes on: box/chris/general/lib/common/ReadLoggingStream.cpp
___________________________________________________________________
Name: svn:eol-style
   + native

Copied: box/chris/general/lib/common/ReadLoggingStream.h (from rev 1602, box/chris/merge/lib/common/ReadLoggingStream.h)
===================================================================
--- box/chris/general/lib/common/ReadLoggingStream.h	                        (rev 0)
+++ box/chris/general/lib/common/ReadLoggingStream.h	2007-04-28 21:19:34 UTC (rev 1603)
@@ -0,0 +1,43 @@
+// --------------------------------------------------------------------------
+//
+// File
+//		Name:    ReadLoggingStream.h
+//		Purpose: Wrapper around IOStreams that logs read progress
+//		Created: 2007/01/16
+//
+// --------------------------------------------------------------------------
+
+#ifndef READLOGGINGSTREAM__H
+#define READLOGGINGSTREAM__H
+
+#include "IOStream.h"
+#include "BoxTime.h"
+
+class ReadLoggingStream : public IOStream
+{
+private:
+	IOStream& mrSource;
+	IOStream::pos_type mOffset, mLength, mTotalRead;
+	box_time_t mStartTime;
+
+public:
+	ReadLoggingStream(IOStream& rSource);
+	
+	virtual int Read(void *pBuffer, int NBytes, int Timeout = IOStream::TimeOutInfinite);
+	virtual pos_type BytesLeftToRead();
+	virtual void Write(const void *pBuffer, int NBytes);
+	virtual pos_type GetPosition() const;
+	virtual void Seek(IOStream::pos_type Offset, int SeekType);
+	virtual void Close();
+	
+	virtual bool StreamDataLeft();
+	virtual bool StreamClosed();
+
+private:
+	ReadLoggingStream(const ReadLoggingStream &rToCopy) 
+	: mrSource(rToCopy.mrSource) { /* do not call */ }
+};
+
+#endif // READLOGGINGSTREAM__H
+
+


Property changes on: box/chris/general/lib/common/ReadLoggingStream.h
___________________________________________________________________
Name: svn:eol-style
   + native

Modified: box/chris/general/lib/server/Daemon.cpp
===================================================================
--- box/chris/general/lib/server/Daemon.cpp	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/lib/server/Daemon.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -101,7 +101,6 @@
 	// Find filename of config file
 	mConfigFileName = DefaultConfigFile;
 	bool haveConfigFile = false;
-	bool singleProcess  = false;
 
 	#ifdef NDEBUG
 	int masterLevel = Log::NOTICE; // need an int to do math with
@@ -125,7 +124,7 @@
 
 			case 'D':
 			{
-				singleProcess = true;
+				mSingleProcess = true;
 			}
 			break;
 
@@ -203,7 +202,7 @@
 
 	if (argc > optind && ::strcmp(argv[optind], "SINGLEPROCESS") == 0)
 	{
-		singleProcess = true; optind++;
+		mSingleProcess = true; optind++;
 	}
 
 	if (argc > optind)
@@ -215,19 +214,18 @@
 
 	Logging::SetGlobalLevel((Log::Level)masterLevel);
 
-	return Main(mConfigFileName, singleProcess);
+	return Main(mConfigFileName);
 }
 
 // --------------------------------------------------------------------------
 //
 // Function
-//		Name:    Daemon::Main(const std::string& rConfigFileName,
-//			 bool singleProcess)
+//		Name:    Daemon::Main(const std::string& rConfigFileName)
 //		Purpose: Starts the daemon off -- equivalent of C main() function
 //		Created: 2003/07/29
 //
 // --------------------------------------------------------------------------
-int Daemon::Main(const std::string &rConfigFileName, bool singleProcess)
+int Daemon::Main(const std::string &rConfigFileName)
 {
 	// Banner (optional)
 	{
@@ -241,7 +239,8 @@
 	std::string pidFileName;
 
 	mConfigFileName = rConfigFileName;
-	bool asDaemon   = !singleProcess;
+	
+	bool asDaemon   = !mSingleProcess;
 
 	try
 	{

Modified: box/chris/general/lib/server/Daemon.h
===================================================================
--- box/chris/general/lib/server/Daemon.h	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/lib/server/Daemon.h	2007-04-28 21:19:34 UTC (rev 1603)
@@ -41,7 +41,7 @@
 public:
 
 	int Main(const char *DefaultConfigFile, int argc, const char *argv[]);
-	int Main(const std::string &rConfigFile, bool singleProcess);
+	int Main(const std::string &rConfigFile);
 	
 	virtual void Run();
 	const Configuration &GetConfiguration() const;
@@ -66,6 +66,7 @@
 
 protected:
 	box_time_t GetLoadedConfigModifiedTime() const;
+	bool IsSingleProcess() { return mSingleProcess; }
 	
 private:
 	static void SignalHandler(int sigraised);
@@ -77,6 +78,7 @@
 	box_time_t mLoadedConfigModifiedTime;
 	bool mReloadConfigWanted;
 	bool mTerminateWanted;
+	bool mSingleProcess;
 	bool mKeepConsoleOpenAfterFork;
 	static Daemon *spDaemon;
 };

Modified: box/chris/general/lib/server/ServerStream.h
===================================================================
--- box/chris/general/lib/server/ServerStream.h	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/lib/server/ServerStream.h	2007-04-28 21:19:34 UTC (rev 1603)
@@ -230,7 +230,7 @@
 					{
 						// Since this is a template parameter, the if() will be optimised out by the compiler
 						#ifndef WIN32 // no fork on Win32
-						if(ForkToHandleRequests)
+						if(ForkToHandleRequests && !IsSingleProcess())
 						{
 							pid_t pid = ::fork();
 							switch(pid)
@@ -285,7 +285,7 @@
 
 				#ifndef WIN32
 				// Clean up child processes (if forking daemon)
-				if(ForkToHandleRequests)
+				if(ForkToHandleRequests && !IsSingleProcess())
 				{
 					int status = 0;
 					int p = 0;
@@ -326,7 +326,7 @@
 		#ifdef WIN32
 		return false;
 		#else
-		return ForkToHandleRequests;
+		return ForkToHandleRequests && !IsSingleProcess();
 		#endif // WIN32
 	}
 

Modified: box/chris/general/test/bbackupd/testbbackupd.cpp
===================================================================
--- box/chris/general/test/bbackupd/testbbackupd.cpp	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/test/bbackupd/testbbackupd.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -2594,7 +2594,7 @@
 		if (!ServerIsAlive(bbackupd_pid)) return 1;
 		if (!ServerIsAlive(bbstored_pid)) return 1;
 
-#ifndef WIN32	
+#ifndef WIN32
 		printf("\n==== Interrupted restore\n");
 		{
 			do_interrupted_restore(context, restoredirid);

Modified: box/chris/general/test/common/testcommon.cpp
===================================================================
--- box/chris/general/test/common/testcommon.cpp	2007-04-28 20:46:35 UTC (rev 1602)
+++ box/chris/general/test/common/testcommon.cpp	2007-04-28 21:19:34 UTC (rev 1603)
@@ -31,6 +31,8 @@
 #include "Archive.h"
 #include "Timer.h"
 #include "Logging.h"
+#include "ZeroStream.h"
+#include "PartialReadStream.h"
 
 #include "MemLeakFindOn.h"
 
@@ -173,6 +175,41 @@
 
 int test(int argc, const char *argv[])
 {
+	// Test PartialReadStream and ReadGatherStream handling of files
+	// over 2GB (refs #2)
+	{
+		char buffer[8];
+
+		ZeroStream zero(0x80000003);
+		zero.Seek(0x7ffffffe, IOStream::SeekType_Absolute);
+		TEST_THAT(zero.GetPosition() == 0x7ffffffe);
+		TEST_THAT(zero.Read(buffer, 8) == 5);
+		TEST_THAT(zero.GetPosition() == 0x80000003);
+		TEST_THAT(zero.Read(buffer, 8) == 0);
+		zero.Seek(0, IOStream::SeekType_Absolute);
+		TEST_THAT(zero.GetPosition() == 0);
+
+		char* buffer2 = new char [0x1000000];
+		TEST_THAT(buffer2 != NULL);
+
+		PartialReadStream part(zero, 0x80000002);
+		for (int i = 0; i < 0x80; i++)
+		{
+			int read = part.Read(buffer2, 0x1000000);
+			TEST_THAT(read == 0x1000000);
+		}
+		TEST_THAT(part.Read(buffer, 8) == 2);
+		TEST_THAT(part.Read(buffer, 8) == 0);
+
+		delete [] buffer2;
+
+		ReadGatherStream gather(false);
+		zero.Seek(0, IOStream::SeekType_Absolute);
+		int component = gather.AddComponent(&zero);
+		gather.AddBlock(component, 0x80000002);
+		TEST_THAT(gather.Read(buffer, 8) == 8);
+	}
+
 	// Test self-deleting temporary file streams
 	{
 		std::string tempfile("testfiles/tempfile");