// read bytes from data socket
const int64_t socketBytesRead = ReadDataSocket(data+bytesReadSoFar, remainingBytes);
- if ( socketBytesRead < 0 )
+ if ( socketBytesRead < 0 ) // error
return -1;
+ else if ( socketBytesRead == 0 ) // EOF
+ return bytesReadSoFar;
bytesReadSoFar += socketBytesRead;
m_filePosition += socketBytesRead;
}
// BamHttp_p.cpp (c) 2011 Derek Barnett
// Marth Lab, Department of Biology, Boston College
// ---------------------------------------------------------------------------
-// Last modified: 10 November 2011 (DB)
+// Last modified: 8 December 2011 (DB)
// ---------------------------------------------------------------------------
// Provides reading/writing of BAM files on HTTP server
// ***************************************************************************
// try to read 'remainingBytes' from socket
const int64_t socketBytesRead = ReadFromSocket(data+bytesReadSoFar, remainingBytes);
- if ( socketBytesRead < 0 )
+ if ( socketBytesRead < 0 ) // error
return -1;
+ else if ( socketBytesRead == 0 ) // EOF
+ return bytesReadSoFar;
bytesReadSoFar += socketBytesRead;
m_filePosition += socketBytesRead;
}
const size_t rangeRemainingBytes = m_endRangeFilePosition - m_filePosition;
const size_t bytesToRead = std::min(remainingBytes, rangeRemainingBytes);
const int64_t socketBytesRead = ReadFromSocket(data+bytesReadSoFar, bytesToRead);
- if ( socketBytesRead < 0 )
+ if ( socketBytesRead < 0 ) // error
return -1;
+ else if ( socketBytesRead == 0 ) // EOF
+ return bytesReadSoFar;
bytesReadSoFar += socketBytesRead;
m_filePosition += socketBytesRead;
}
RaiiBuffer tmp(0x8000);
int64_t numBytesRead = 0;
while ( numBytesRead < m_filePosition ) {
- int64_t result = ReadFromSocket(tmp.Buffer, 0x8000);
- if ( result < 0 ) {
+
+ const int64_t remaining = m_filePosition - numBytesRead;
+ const size_t bytesToRead = static_cast<size_t>( (remaining > 0x8000) ? 0x8000 : remaining );
+ const int64_t socketBytesRead = ReadFromSocket(tmp.Buffer, bytesToRead);
+ if ( socketBytesRead < 0 ) { // error
Close();
return false;
}
- numBytesRead += result;
+ else if ( socketBytesRead == 0 ) // EOF
+ break;
+
+ numBytesRead += socketBytesRead;
}
// return success
- return true;
+ return ( numBytesRead == m_filePosition);
}
// on any other reponse status
// RollingBuffer_p.h (c) 2011 Derek Barnett
// Marth Lab, Department of Biology, Boston College
// ---------------------------------------------------------------------------
-// Last modified: 10 November 2011 (DB)
+// Last modified: 7 December 2011 (DB)
// ---------------------------------------------------------------------------
// Provides a dynamic I/O FIFO byte queue, which removes bytes as they are
// read from the front of the buffer and grows to accept bytes being written
// reads until newline (or up to @maxLen bytes)
// returns exactly how many bytes were read from buffer
size_t ReadLine(char* dest, size_t max);
-
- const char* ReadPointer(void) const; // returns a C-fxn compatible char* to byte data
- char* Reserve(size_t n); // ensures that buffer contains space for @n incoming bytes, returns write-able char*
- size_t Size(void) const; // returns current number of bytes stored in buffer
- void Write(const char* src, size_t n); // reserves space for @n bytes, then appends contents of @src to buffer
+ // returns a C-fxn compatible char* to byte data
+ const char* ReadPointer(void) const;
+ // ensures that buffer contains space for @n incoming bytes, returns write-able char*
+ char* Reserve(size_t n);
+ // returns current number of bytes stored in buffer
+ size_t Size(void) const;
+ // reserves space for @n bytes, then appends contents of @src to buffer
+ void Write(const char* src, size_t n);
// data members
private:
}
int64_t TcpSocketEngine::nativeRead(char* dest, size_t max) {
-
- if ( !IsValid() )
- return -1;
-
- ssize_t ret = read(m_socketDescriptor, dest, max);
- if ( ret < 0 ) {
- ret = -1;
- switch ( errno ) {
- case EAGAIN :
- // No data was available for reading
- ret = -2;
- break;
- case ECONNRESET :
- ret = 0;
- break;
- default:
- break;
- }
- }
+ const ssize_t ret = read(m_socketDescriptor, dest, max);
return static_cast<int64_t>(ret);
}
}
int64_t TcpSocketEngine::nativeWrite(const char* data, size_t length) {
-
- ssize_t writtenBytes = write(m_socketDescriptor, data, length);
- if ( writtenBytes < 0 ) {
- switch (errno) {
- case EPIPE:
- case ECONNRESET:
- writtenBytes = -1;
- m_socketError = TcpSocket::RemoteHostClosedError;
- m_errorString = "remote host closed connection";
- Close();
- break;
- case EAGAIN:
- writtenBytes = 0;
- break;
- default:
- break;
- }
- }
+ const ssize_t writtenBytes = write(m_socketDescriptor, data, length);
return static_cast<int64_t>(writtenBytes);
}
// TcpSocket_p.cpp (c) 2011 Derek Barnett
// Marth Lab, Department of Biology, Boston College
// ---------------------------------------------------------------------------
-// Last modified: 10 November 2011 (DB)
+// Last modified: 7 December 2011 (DB)
// ---------------------------------------------------------------------------
// Provides basic TCP I/O interface
// ***************************************************************************
}
// fetch data from socket, return 0 for success, -1 for failure
- // since this should be called in a loop, we'll pull the actual bytes on next iteration
- return ( ReadFromSocket() ? 0 : -1 );
+ // since this should be called in a loop,
+ // we'll pull the actual bytes from the buffer on next iteration
+ const int64_t socketBytesRead = ReadFromSocket();
+ if ( socketBytesRead < 0 ) {
+ // TODO: set error string/state ?
+ return -1;
+ }
+
+ // we should have data now in buffer, try to fetch requested amount
+ // if nothing in buffer, we will return 0 bytes read (signals EOF reached)
+ const size_t numBytesRead = m_readBuffer.Read(data, numBytes);
+ return static_cast<int64_t>(numBytesRead);
}
-bool TcpSocket::ReadFromSocket(void) {
+int64_t TcpSocket::ReadFromSocket(void) {
// check for any socket engine errors
if ( !m_engine->IsValid() ) {
m_errorString = "TcpSocket::ReadFromSocket - socket disconnected";
ResetSocketEngine();
- return false;
+ return -1;
}
// wait for ready read
bool timedOut;
- bool isReadyRead = m_engine->WaitForRead(5000, &timedOut);
+ const bool isReadyRead = m_engine->WaitForRead(5000, &timedOut);
// if not ready
if ( !isReadyRead ) {
if ( timedOut ) {
m_errorString = "TcpSocket::ReadFromSocket - timed out waiting for ready read";
// get error from engine ?
- return false;
+ return -1;
}
// otherwise, there was an error
else {
m_errorString = "TcpSocket::ReadFromSocket - encountered error while waiting for ready read";
// get error from engine ?
- return false;
+ return -1;
}
}
- // #########################################################################
- // clean this up - smells funky, but it's a key step so it has to be right
- // #########################################################################
-
// get number of bytes available from socket
- // (if 0, still try to read some data so we don't trigger any OS event behavior
- // that respond to repeated access to a remote closed socket)
- int64_t bytesToRead = m_engine->NumBytesAvailable();
+ const int64_t bytesToRead = m_engine->NumBytesAvailable();
if ( bytesToRead < 0 ) {
m_errorString = "TcpSocket::ReadFromSocket - encountered error while determining numBytesAvailable";
// get error from engine ?
- return false;
+ return -1;
}
- else if ( bytesToRead == 0 )
- bytesToRead = 4096;
// make space in buffer & read from socket
char* buffer = m_readBuffer.Reserve(bytesToRead);
- int64_t numBytesRead = m_engine->Read(buffer, bytesToRead);
-
- // if error while reading
+ const int64_t numBytesRead = m_engine->Read(buffer, bytesToRead);
if ( numBytesRead == -1 ) {
m_errorString = "TcpSocket::ReadFromSocket - encountered error while reading bytes";
// get error from engine ?
- return false;
}
- // handle special case (no data, but not error)
- if ( numBytesRead == -2 )
- m_readBuffer.Chop(bytesToRead);
-
- // return success
- return true;
+ // return number of bytes actually read
+ return numBytesRead;
}
string TcpSocket::ReadLine(int64_t max) {
// wait for our socket to be write-able
bool timedOut;
- bool isReadyWrite = m_engine->WaitForWrite(3000, &timedOut);
+ const bool isReadyWrite = m_engine->WaitForWrite(3000, &timedOut);
if ( isReadyWrite )
bytesWritten = m_engine->Write(data, numBytes);
else {
// TcpSocket_p.h (c) 2011 Derek Barnett
// Marth Lab, Department of Biology, Boston College
// ---------------------------------------------------------------------------
-// Last modified: 10 November 2011 (DB)
+// Last modified: 7 December 2011 (DB)
// ---------------------------------------------------------------------------
// Provides basic TCP I/O interface
// ***************************************************************************
const std::string& port,
IBamIODevice::OpenMode mode);
bool InitializeSocketEngine(HostAddress::NetworkProtocol protocol);
- bool ReadFromSocket(void);
+ int64_t ReadFromSocket(void);
void ResetSocketEngine(void);
// data members