Add TFDTransport: a dead-simple wrapper around a file-descriptor.
git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@665644 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/lib/cpp/Makefile.am b/lib/cpp/Makefile.am
index 571c4ff..feaebaf 100644
--- a/lib/cpp/Makefile.am
+++ b/lib/cpp/Makefile.am
@@ -34,6 +34,7 @@
src/protocol/TJSONProtocol.cpp \
src/protocol/TBase64Utils.cpp \
src/transport/TTransportException.cpp \
+ src/transport/TFDTransport.cpp \
src/transport/TFileTransport.cpp \
src/transport/THttpClient.cpp \
src/transport/TSocket.cpp \
@@ -94,6 +95,7 @@
include_transportdir = $(include_thriftdir)/transport
include_transport_HEADERS = \
+ src/transport/TFDTransport.h \
src/transport/TFileTransport.h \
src/transport/TServerSocket.h \
src/transport/TServerTransport.h \
diff --git a/lib/cpp/src/transport/TFDTransport.cpp b/lib/cpp/src/transport/TFDTransport.cpp
new file mode 100644
index 0000000..bbdcb19
--- /dev/null
+++ b/lib/cpp/src/transport/TFDTransport.cpp
@@ -0,0 +1,64 @@
+// Copyright (c) 2006- Facebook
+// Distributed under the Thrift Software License
+//
+// See accompanying file LICENSE or visit the Thrift site at:
+// http://developers.facebook.com/thrift/
+
+#include <cerrno>
+#include <exception>
+
+#include <transport/TFDTransport.h>
+
+#include <unistd.h>
+
+using namespace std;
+
+namespace facebook { namespace thrift { namespace transport {
+
+void TFDTransport::close() {
+ if (!isOpen()) {
+ return;
+ }
+
+ int rv = ::close(fd_);
+ int errno_copy = errno;
+ fd_ = -1;
+ // Have to check uncaught_exception because this is called in the destructor.
+ if (rv < 0 && !std::uncaught_exception()) {
+ throw TTransportException(TTransportException::UNKNOWN,
+ "TFDTransport::close()",
+ errno_copy);
+ }
+}
+
+uint32_t TFDTransport::read(uint8_t* buf, uint32_t len) {
+ ssize_t rv = ::read(fd_, buf, len);
+ if (rv < 0) {
+ int errno_copy = errno;
+ throw TTransportException(TTransportException::UNKNOWN,
+ "TFDTransport::read()",
+ errno_copy);
+ }
+ return rv;
+}
+
+void TFDTransport::write(const uint8_t* buf, uint32_t len) {
+ while (len > 0) {
+ ssize_t rv = ::write(fd_, buf, len);
+
+ if (rv < 0) {
+ int errno_copy = errno;
+ throw TTransportException(TTransportException::UNKNOWN,
+ "TFDTransport::write()",
+ errno_copy);
+ } else if (rv == 0) {
+ throw TTransportException(TTransportException::END_OF_FILE,
+ "TFDTransport::write()");
+ }
+
+ buf += rv;
+ len -= rv;
+ }
+}
+
+}}} // facebook::thrift::transport
diff --git a/lib/cpp/src/transport/TFDTransport.h b/lib/cpp/src/transport/TFDTransport.h
new file mode 100644
index 0000000..e70f987
--- /dev/null
+++ b/lib/cpp/src/transport/TFDTransport.h
@@ -0,0 +1,61 @@
+// Copyright (c) 2006- Facebook
+// Distributed under the Thrift Software License
+//
+// See accompanying file LICENSE or visit the Thrift site at:
+// http://developers.facebook.com/thrift/
+
+#ifndef _THRIFT_TRANSPORT_TFDTRANSPORT_H_
+#define _THRIFT_TRANSPORT_TFDTRANSPORT_H_ 1
+
+#include <string>
+#include <sys/time.h>
+
+#include "TTransport.h"
+#include "TServerSocket.h"
+
+namespace facebook { namespace thrift { namespace transport {
+
+/**
+ * Dead-simple wrapper around a file descriptor.
+ *
+ * @author David Reiss <dreiss@facebook.com>
+ */
+class TFDTransport : public TTransport {
+ public:
+ enum ClosePolicy {
+ NO_CLOSE_ON_DESTROY = 0,
+ CLOSE_ON_DESTROY = 1,
+ };
+
+ TFDTransport(int fd, ClosePolicy close_policy = NO_CLOSE_ON_DESTROY)
+ : fd_(fd)
+ , close_policy_(close_policy)
+ {}
+
+ ~TFDTransport() {
+ if (close_policy_ == CLOSE_ON_DESTROY) {
+ close();
+ }
+ }
+
+ bool isOpen() { return fd_ >= 0; }
+
+ void open() {}
+
+ void close();
+
+ uint32_t read(uint8_t* buf, uint32_t len);
+
+ void write(const uint8_t* buf, uint32_t len);
+
+ void setFD(int fd) { fd_ = fd; }
+ int getFD() { return fd_; }
+
+ protected:
+ int fd_;
+ ClosePolicy close_policy_;
+};
+
+}}} // facebook::thrift::transport
+
+#endif // #ifndef _THRIFT_TRANSPORT_TFDTRANSPORT_H_
diff --git a/test/Makefile.am b/test/Makefile.am
index 5de2f1b..5490de8 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -27,6 +27,7 @@
Benchmark_LDADD = libtestgencpp.la
check_PROGRAMS = \
+ TFDTransportTest \
DebugProtoTest \
JSONProtoTest \
OptionalRequiredTest \
@@ -43,6 +44,15 @@
UnitTests_LDADD = libtestgencpp.la
#
+# TFDTransportTest
+#
+TFDTransportTest_SOURCES = \
+ TFDTransportTest.cpp
+
+TFDTransportTest_LDADD = \
+ $(top_srcdir)/lib/cpp/libthrift.la
+
+#
# DebugProtoTest
#
DebugProtoTest_SOURCES = \
diff --git a/test/TFDTransportTest.cpp b/test/TFDTransportTest.cpp
new file mode 100644
index 0000000..dfc2d27
--- /dev/null
+++ b/test/TFDTransportTest.cpp
@@ -0,0 +1,37 @@
+#include <cstdlib>
+#include <stdexcept>
+#include <Thrift.h>
+#include <transport/TFDTransport.h>
+using facebook::thrift::transport::TTransportException;
+using facebook::thrift::transport::TFDTransport;
+
+class DummyException : std::exception {
+};
+
+int main() {
+ {
+ TFDTransport t(256, TFDTransport::NO_CLOSE_ON_DESTROY);
+ }
+
+ try {
+ {
+ TFDTransport t(256, TFDTransport::CLOSE_ON_DESTROY);
+ }
+ std::abort();
+ } catch (TTransportException) {
+ }
+
+ try {
+ {
+ TFDTransport t(256, TFDTransport::CLOSE_ON_DESTROY);
+ throw DummyException();
+ }
+ std::abort();
+ } catch (TTransportException&) {
+ abort();
+ } catch (DummyException&) {
+ }
+
+ return 0;
+
+}