]> git.donarmstrong.com Git - bamtools.git/commitdiff
Fixed EOF issues on *nix platforms
authorderek <derekwbarnett@gmail.com>
Thu, 8 Dec 2011 05:26:10 +0000 (00:26 -0500)
committerderek <derekwbarnett@gmail.com>
Thu, 8 Dec 2011 05:26:10 +0000 (00:26 -0500)
src/api/internal/io/BamFtp_p.cpp
src/api/internal/io/BamHttp_p.cpp
src/api/internal/io/RollingBuffer_p.h
src/api/internal/io/TcpSocketEngine_unix_p.cpp
src/api/internal/io/TcpSocket_p.cpp
src/api/internal/io/TcpSocket_p.h

index d9f933cd448ee3034c36afa0db2e90bb092f2e35..a90a35743a91507ece1ed17078b5d2e7e7195cdb 100644 (file)
@@ -355,8 +355,10 @@ int64_t BamFtp::Read(char* data, const unsigned int numBytes) {
 
         // 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;
     }
index e2ade70a1327f4ea90d4928ae28b6ec4e26f17a1..ba573372b9f45265a34a4b7ba5a0963491804834 100644 (file)
@@ -2,7 +2,7 @@
 // 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
 // ***************************************************************************
@@ -229,8 +229,10 @@ int64_t BamHttp::Read(char* data, const unsigned int numBytes) {
 
             // 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;
         }
@@ -247,8 +249,10 @@ int64_t BamHttp::Read(char* data, const unsigned int numBytes) {
                 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;
             }
@@ -324,16 +328,22 @@ bool BamHttp::ReceiveResponse(void) {
         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
index e995f26bdae764d119d82b6f22ef3c39f04d3190..55550c04390c85517409a2dcf9659f1f89ea0372 100644 (file)
@@ -2,7 +2,7 @@
 // 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
@@ -62,11 +62,14 @@ class RollingBuffer {
         // 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:
index efcdf8d92ac3046ee48aaf6c3c649377d3ed13fe..5b100e48b2ea90874e1d644024d9474aa681147b 100644 (file)
@@ -182,25 +182,7 @@ int64_t TcpSocketEngine::nativeNumBytesAvailable(void) const {
 }
 
 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);
 }
 
@@ -225,23 +207,6 @@ int TcpSocketEngine::nativeSelect(int msecs, bool isRead) const {
 }
 
 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);
 }
index 4ff53a8a1ae9c55bdcaff89aa362530bb9cb94c2..b27635ea5de3a41fb07c6006378566037f125617 100644 (file)
@@ -2,7 +2,7 @@
 // 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
 // ***************************************************************************
@@ -243,22 +243,32 @@ int64_t TcpSocket::Read(char* data, const unsigned int numBytes) {
     }
 
     // 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 ) {
@@ -267,50 +277,35 @@ bool TcpSocket::ReadFromSocket(void) {
         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) {
@@ -415,7 +410,7 @@ int64_t TcpSocket::Write(const char* data, const unsigned int numBytes) {
 
     // 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 {
index 3c5f2fc82e00b40ca620753b271fa97e52520730..a25a11e0ff845f9ab847120c50784ef721a01e48 100644 (file)
@@ -2,7 +2,7 @@
 // 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
 // ***************************************************************************
@@ -95,7 +95,7 @@ class TcpSocket {
                          const std::string& port,
                          IBamIODevice::OpenMode mode);
         bool InitializeSocketEngine(HostAddress::NetworkProtocol protocol);
-        bool ReadFromSocket(void);
+        int64_t ReadFromSocket(void);
         void ResetSocketEngine(void);
 
     // data members