Skip to content
Permalink
Browse files

Make IOStream::CopyStreamTo honour timeout

Throw an exception on network timeout.  This is safer than returning false,
which isn't checked in many places, and allows us to return the number of bytes
copied instead.

(cherry picked from commit e38d3d7)
  • Loading branch information
qris committed Oct 13, 2015
1 parent dedb10f commit 1e390cc69aa7fcbca0619b83153379acb04c0a7d
@@ -528,9 +528,21 @@ int64_t BackupStoreContext::AddFile(IOStream &rFile, int64_t InDirectory,
if(DiffFromFileID == 0)
{
// A full file, just store to disc
if(!rFile.CopyStreamTo(storeFile, BACKUP_STORE_TIMEOUT))
try
{
rFile.CopyStreamTo(storeFile, BACKUP_STORE_TIMEOUT);
}
catch(CommonException &e)
{
THROW_EXCEPTION(BackupStoreException, ReadFileFromStreamTimedOut)
if(EXCEPTION_IS_TYPE(e, CommonException, IOStreamTimedOut))
{
THROW_EXCEPTION_MESSAGE(BackupStoreException,
ReadFileFromStreamTimedOut, e.GetMessage());
}
else
{
throw;
}
}
}
else
@@ -566,9 +578,21 @@ int64_t BackupStoreContext::AddFile(IOStream &rFile, int64_t InDirectory,
#endif

// Stream the incoming diff to this temporary file
if(!rFile.CopyStreamTo(diff, BACKUP_STORE_TIMEOUT))
try
{
rFile.CopyStreamTo(diff, BACKUP_STORE_TIMEOUT);
}
catch(CommonException &e)
{
THROW_EXCEPTION(BackupStoreException, ReadFileFromStreamTimedOut)
if(EXCEPTION_IS_TYPE(e, CommonException, IOStreamTimedOut))
{
THROW_EXCEPTION_MESSAGE(BackupStoreException,
ReadFileFromStreamTimedOut, e.GetMessage());
}
else
{
throw;
}
}

// Verify the diff
@@ -57,3 +57,4 @@ DatabaseIterateFailed 49 Failed to iterate over the database keys
ReferenceNotFound 50 The database does not contain an expected reference
TimersNotInitialised 51 The timer framework should have been ready at this point
InvalidConfiguration 52 Some required values are missing or incorrect in the configuration file.
IOStreamTimedOut 53 A network operation timed out.
@@ -188,22 +188,24 @@ IOStream::pos_type IOStream::BytesLeftToRead()
//
// Function
// Name: IOStream::CopyStreamTo(IOStream &, int Timeout)
// Purpose: Copies the entire stream to another stream (reading from this,
// writing to rCopyTo). Returns whether the copy completed (ie
// StreamDataLeft() returns false)
// Purpose: Copies the entire stream to another stream (reading
// from this, writing to rCopyTo). Returns the number
// of bytes copied. Throws an exception if a network
// timeout occurs.
// Created: 2003/08/26
//
// --------------------------------------------------------------------------
bool IOStream::CopyStreamTo(IOStream &rCopyTo, int Timeout, int BufferSize)
IOStream::pos_type IOStream::CopyStreamTo(IOStream &rCopyTo, int Timeout, int BufferSize)
{
// Make sure there's something to do before allocating that buffer
if(!StreamDataLeft())
{
return true; // complete, even though nothing happened
return 0;
}

// Buffer
MemoryBlockGuard<char*> buffer(BufferSize);
IOStream::pos_type bytes_copied = 0;

// Get copying!
while(StreamDataLeft())
@@ -212,17 +214,20 @@ bool IOStream::CopyStreamTo(IOStream &rCopyTo, int Timeout, int BufferSize)
int bytes = Read(buffer, BufferSize, Timeout);
if(bytes == 0 && StreamDataLeft())
{
return false; // incomplete, timed out
THROW_EXCEPTION_MESSAGE(CommonException, IOStreamTimedOut,
"Timed out copying stream");
}

// Write some data
if(bytes != 0)
{
rCopyTo.Write(buffer, bytes);
rCopyTo.Write(buffer, bytes, Timeout);
}

bytes_copied += bytes;
}

return true; // completed
return bytes_copied; // completed
}

// --------------------------------------------------------------------------
@@ -63,7 +63,8 @@ class IOStream

// Utility functions
bool ReadFullBuffer(void *pBuffer, int NBytes, int *pNBytesRead, int Timeout = IOStream::TimeOutInfinite);
bool CopyStreamTo(IOStream &rCopyTo, int Timeout = IOStream::TimeOutInfinite, int BufferSize = 1024);
IOStream::pos_type CopyStreamTo(IOStream &rCopyTo,
int Timeout = IOStream::TimeOutInfinite, int BufferSize = 1024);
void Flush(int Timeout = IOStream::TimeOutInfinite);

static int ConvertSeekTypeToOSWhence(int SeekType);
@@ -763,10 +763,22 @@ void Protocol::SendStream(IOStream &rStream)
else
{
// Fixed size stream, send it all in one go
if(!rStream.CopyStreamTo(*mapConn, GetTimeout(),
4096 /* slightly larger buffer */))
try
{
rStream.CopyStreamTo(*mapConn, GetTimeout(),
4096 /* slightly larger buffer */);
}
catch(CommonException &e)
{
THROW_EXCEPTION(ConnectionException, Protocol_TimeOutWhenSendingStream)
if(EXCEPTION_IS_TYPE(e, CommonException, IOStreamTimedOut))
{
THROW_EXCEPTION_MESSAGE(ConnectionException,
Protocol_TimeOutWhenSendingStream, e.GetMessage());
}
else
{
throw;
}
}
}
// Make sure everything is written

0 comments on commit 1e390cc

Please sign in to comment.
You can’t perform that action at this time.