Thrift: C++ peek() method and TException not Exception


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664876 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/src/transport/TSocket.cpp b/lib/cpp/src/transport/TSocket.cpp
index de3bea7..8b9048c 100644
--- a/lib/cpp/src/transport/TSocket.cpp
+++ b/lib/cpp/src/transport/TSocket.cpp
@@ -43,6 +43,8 @@
   lingerOn_(1),
   lingerVal_(0),
   noDelay_(1) {
+  recvTimeval_.tv_sec = (int)(recvTimeout_/1000);
+  recvTimeval_.tv_usec = (int)((recvTimeout_%1000)*1000);
 }
 
 TSocket::TSocket(int socket) :
@@ -55,6 +57,8 @@
   lingerOn_(1),
   lingerVal_(0),
   noDelay_(1) {
+  recvTimeval_.tv_sec = (int)(recvTimeout_/1000);
+  recvTimeval_.tv_usec = (int)((recvTimeout_%1000)*1000);
 }
   
 TSocket::~TSocket() {
@@ -65,6 +69,20 @@
   return (socket_ > 0); 
 }
 
+bool TSocket::peek() {
+  if (!isOpen()) {
+    return false;
+  }
+  uint8_t buf;
+  int r = recv(socket_, &buf, 1, MSG_PEEK);
+  if (r == -1) {
+    perror("TSocket::peek()");
+    close();
+    throw TTransportException(TTX_UNKNOWN, "recv() ERROR:" + errno);
+  }
+  return (r > 0);
+}
+
 void TSocket::open() {
   // Create socket
   socket_ = socket(AF_INET, SOCK_STREAM, 0);
@@ -322,12 +340,14 @@
 
 void TSocket::setRecvTimeout(int ms) {
   recvTimeout_ = ms;
+  recvTimeval_.tv_sec = (int)(recvTimeout_/1000);
+  recvTimeval_.tv_usec = (int)((recvTimeout_%1000)*1000);
   if (socket_ <= 0) {
     return;
   }
 
-  struct timeval r = {(int)(recvTimeout_/1000),
-                      (int)((recvTimeout_%1000)*1000)};
+  // Copy because select may modify
+  struct timeval r = recvTimeval_;
   int ret = setsockopt(socket_, SOL_SOCKET, SO_RCVTIMEO, &r, sizeof(r));
   if (ret == -1) {
     perror("TSocket::setRecvTimeout()");
diff --git a/lib/cpp/src/transport/TSocket.h b/lib/cpp/src/transport/TSocket.h
index b946b6a..8137984 100644
--- a/lib/cpp/src/transport/TSocket.h
+++ b/lib/cpp/src/transport/TSocket.h
@@ -2,6 +2,7 @@
 #define _THRIFT_TRANSPORT_TSOCKET_H_ 1
 
 #include <string>
+#include <sys/time.h>
 
 #include "TTransport.h"
 #include "TServerSocket.h"
@@ -45,6 +46,11 @@
   bool isOpen();
 
   /**
+   * Calls select on the socket to see if there is more data available.
+   */
+  bool peek();
+
+  /**
    * Creates and opens the UNIX socket.
    *
    * @throws TTransportException If the socket could not connect
@@ -131,6 +137,9 @@
 
   /** Nodelay */
   bool noDelay_;
+
+  /** Recv timeout timeval */
+  struct timeval recvTimeval_;
 };
 
 }}} // facebook::thrift::transport
diff --git a/lib/cpp/src/transport/TTransport.h b/lib/cpp/src/transport/TTransport.h
index 7b4cbe1..5e4ae6b 100644
--- a/lib/cpp/src/transport/TTransport.h
+++ b/lib/cpp/src/transport/TTransport.h
@@ -24,7 +24,21 @@
   /**
    * Whether this transport is open.
    */
-  virtual bool isOpen() { return false; }
+  virtual bool isOpen() {
+    return false;
+  }
+
+  /**
+   * Tests whether there is more data to read or if the remote side is
+   * still open. By default this is true whenever the transport is open,
+   * but implementations should add logic to test for this condition where
+   * possible (i.e. on a socket).
+   * This is used by a server to check if it should listen for another
+   * request.
+   */
+  virtual bool peek() {
+    return isOpen();
+  }
 
   /**
    * Opens the transport for communications.
diff --git a/lib/cpp/src/transport/TTransportException.h b/lib/cpp/src/transport/TTransportException.h
index c54084d..e02eb70 100644
--- a/lib/cpp/src/transport/TTransportException.h
+++ b/lib/cpp/src/transport/TTransportException.h
@@ -23,21 +23,25 @@
  *
  * @author Mark Slee <mcslee@facebook.com>
  */
-class TTransportException {
+class TTransportException : public facebook::thrift::TException {
  public:
   TTransportException() :
-    type_(TTX_UNKNOWN), message_() {}
+    facebook::thrift::TException(),
+    type_(TTX_UNKNOWN) {}
 
   TTransportException(TTransportExceptionType type) :
-    type_(type), message_() {}
+    facebook::thrift::TException(), 
+    type_(type) {}
 
-  TTransportException(std::string message) :
-    type_(TTX_UNKNOWN), message_(message) {}
+  TTransportException(const std::string message) :
+    facebook::thrift::TException(message),
+    type_(TTX_UNKNOWN) {}
 
-  TTransportException(TTransportExceptionType type, std::string message) :
-    type_(type), message_(message) {}
+  TTransportException(TTransportExceptionType type, const std::string message) :
+    facebook::thrift::TException(message),
+    type_(type) {}
 
-  ~TTransportException() {}
+  virtual ~TTransportException() throw() {}
 
   /**
    * Returns an error code that provides information about the type of error
@@ -45,21 +49,14 @@
    *
    * @return Error code
    */
-  TTransportExceptionType getType() { return type_; }
+  TTransportExceptionType getType() {
+    return type_;
+  }
  
-  /**
-   * Returns an informative message about what caused this error.
-   *
-   * @return Error string
-   */
-  const std::string& getMessage() { return message_; }
-
  protected:
   /** Error code */
   TTransportExceptionType type_;
 
-  /** Description */
-  std::string message_;
 };
 
 }}} // facebook::thrift::transport
diff --git a/lib/cpp/src/transport/TTransportUtils.cpp b/lib/cpp/src/transport/TTransportUtils.cpp
index d9f4775..02454e3 100644
--- a/lib/cpp/src/transport/TTransportUtils.cpp
+++ b/lib/cpp/src/transport/TTransportUtils.cpp
@@ -16,7 +16,6 @@
       buf += rLen_-rPos_;
     }    
     // Get more from underlying transport up to buffer size
-    // TODO: should this be a readAll?
     rLen_ = transport_->read(rBuf_, rBufSize_);
     rPos_ = 0;
   }
diff --git a/lib/cpp/src/transport/TTransportUtils.h b/lib/cpp/src/transport/TTransportUtils.h
index 8d8d093..a8003cf 100644
--- a/lib/cpp/src/transport/TTransportUtils.h
+++ b/lib/cpp/src/transport/TTransportUtils.h
@@ -71,6 +71,14 @@
     return transport_->isOpen();
   }
   
+  bool peek() {    
+    if (rPos_ >= rLen_) {
+      rLen_ = transport_->read(rBuf_, rBufSize_);
+      rPos_ = 0;
+    }
+    return (rLen_ > rPos_);
+  }
+
   void open() {
     transport_->open();
   }
@@ -177,6 +185,13 @@
     return transport_->isOpen();
   }
 
+  bool peek() {
+    if (rPos_ < rLen_) {
+      return true;
+    }
+    return transport_->peek();
+  }
+
   void close() {
     transport_->close();
   }
@@ -260,7 +275,10 @@
     return true;
   }
 
- 
+  bool peek() {
+    return (rPos_ < wPos_);
+  }
+
   void open() {}
 
   void close() {}