src/transport/THttpServer.h \
src/transport/TSocket.h \
src/transport/TSocketPool.h \
+ src/transport/TVirtualTransport.h \
src/transport/TTransport.h \
src/transport/TTransportException.h \
src/transport/TTransportUtils.h \
#define T_LOG_OPER(format_string,...)
#endif
+
+/**
+ * T_GLOBAL_DEBUG_VIRTUAL = 0: normal operation,
+ * virtual call debug messages disabled
+ * T_GLOBAL_DEBUG_VIRTUAL = 1: log a debug messages whenever an
+ * avoidable virtual call is made
+ */
+#define T_GLOBAL_DEBUG_VIRTUAL 0
+
+/**
+ * Log a message indicating that a virtual function call is being made.
+ *
+ * This should be disabled during normal use. It is intended to be used
+ * only to help debug serialization performance.
+ */
+#if T_GLOBAL_DEBUG_VIRTUAL > 0
+ #define T_VIRTUAL_CALL() \
+ fprintf(stderr,"[%s,%d] virtual call\n", __FILE__, __LINE__)
+#else
+ #define T_VIRTUAL_CALL()
+#endif
+
#endif // #ifndef _THRIFT_TLOGGING_H_
#include "boost/scoped_array.hpp"
#include <transport/TTransport.h>
+#include <transport/TVirtualTransport.h>
#ifdef __GNUC__
#define TDB_LIKELY(val) (__builtin_expect((val), 1))
* that have to be done when the buffers are full or empty.
*
*/
-class TBufferBase : public TTransport {
+class TBufferBase : public TVirtualTransport<TBufferBase> {
public:
rBase_ = new_rBase;
return len;
}
- return facebook::thrift::transport::readAll(*this, buf, len);
+ return apache::thrift::transport::readAll(*this, buf, len);
}
/**
* stored to an in memory buffer before being written out.
*
*/
-class TBufferedTransport : public TBufferBase {
+class TBufferedTransport
+ : public TVirtualTransport<TBufferedTransport, TBufferBase> {
public:
static const int DEFAULT_BUFFER_SIZE = 512;
return transport_;
}
+ /*
+ * TVirtualTransport provides a default implementation of readAll().
+ * We want to use the TBufferBase version instead.
+ */
+ using TBufferBase::readAll;
+
protected:
void initPointers() {
setReadBuffer(rBuf_.get(), 0);
* other end to always do fixed-length reads.
*
*/
-class TFramedTransport : public TBufferBase {
+class TFramedTransport
+ : public TVirtualTransport<TFramedTransport, TBufferBase> {
public:
static const int DEFAULT_BUFFER_SIZE = 512;
return transport_;
}
+ /*
+ * TVirtualTransport provides a default implementation of readAll().
+ * We want to use the TBufferBase version instead.
+ */
+ using TBufferBase::readAll;
+
protected:
/**
* Reads a frame of input from the underlying stream.
* doubles as necessary. We've considered using scoped
*
*/
-class TMemoryBuffer : public TBufferBase {
+class TMemoryBuffer : public TVirtualTransport<TMemoryBuffer, TBufferBase> {
private:
// Common initialization done by all constructors.
// that had been provided by getWritePtr().
void wroteBytes(uint32_t len);
+ /*
+ * TVirtualTransport provides a default implementation of readAll().
+ * We want to use the TBufferBase version instead.
+ */
+ using TBufferBase::readAll;
+
protected:
void swap(TMemoryBuffer& that) {
using std::swap;
#include <sys/time.h>
#include "TTransport.h"
-#include "TServerSocket.h"
+#include "TVirtualTransport.h"
namespace apache { namespace thrift { namespace transport {
* Dead-simple wrapper around a file descriptor.
*
*/
-class TFDTransport : public TTransport {
+class TFDTransport : public TVirtualTransport<TFDTransport> {
public:
enum ClosePolicy
{ NO_CLOSE_ON_DESTROY = 0
return eofSleepTime_;
}
+ /*
+ * Override TTransport *_virt() functions to invoke our implementations.
+ * We cannot use TVirtualTransport to provide these, since we need to inherit
+ * virtually from TTransport.
+ */
+ virtual uint32_t read_virt(uint8_t* buf, uint32_t len) {
+ return this->read(buf, len);
+ }
+ virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) {
+ return this->readAll(buf, len);
+ }
+ virtual void write_virt(const uint8_t* buf, uint32_t len) {
+ this->write(buf, len);
+ }
+
private:
// helper functions for writing to a file
void enqueueEvent(const uint8_t* buf, uint32_t eventLen, bool blockUntilFlush);
#define _THRIFT_TRANSPORT_THTTPTRANSPORT_H_ 1
#include <transport/TBufferTransports.h>
+#include "TVirtualTransport.h"
namespace apache { namespace thrift { namespace transport {
* here is a VERY basic HTTP/1.1 client which supports HTTP 100 Continue,
* chunked transfer encoding, keepalive, etc. Tested against Apache.
*/
-class THttpTransport : public TTransport {
+class THttpTransport : public TVirtualTransport<THttpTransport> {
public:
THttpTransport(boost::shared_ptr<TTransport> transport);
#include <cstdlib>
#include <transport/TTransport.h>
+#include <transport/TVirtualTransport.h>
namespace apache { namespace thrift { namespace transport { namespace test {
* the read amount is randomly reduced before being passed through.
*
*/
-class TShortReadTransport : public TTransport {
+class TShortReadTransport : public TVirtualTransport<TShortReadTransport> {
public:
TShortReadTransport(boost::shared_ptr<TTransport> transport, double full_prob)
: transport_(transport)
#include <netdb.h>
#include "TTransport.h"
+#include "TVirtualTransport.h"
#include "TServerSocket.h"
namespace apache { namespace thrift { namespace transport {
* TCP Socket implementation of the TTransport interface.
*
*/
-class TSocket : public TTransport {
+class TSocket : public TVirtualTransport<TSocket> {
/**
* We allow the TServerSocket acceptImpl() method to access the private
* members of a socket so that it can access the TSocket(int socket)
* @return How many bytes were actually read
* @throws TTransportException If an error occurs
*/
- virtual uint32_t read(uint8_t* /* buf */, uint32_t /* len */) {
- throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot read.");
+ uint32_t read(uint8_t* buf, uint32_t len) {
+ T_VIRTUAL_CALL();
+ return read_virt(buf, len);
+ }
+ virtual uint32_t read_virt(uint8_t* /* buf */, uint32_t /* len */) {
+ throw TTransportException(TTransportException::NOT_OPEN,
+ "Base TTransport cannot read.");
}
/**
* @return How many bytes read, which must be equal to size
* @throws TTransportException If insufficient data was read
*/
- virtual uint32_t readAll(uint8_t* buf, uint32_t len) {
+ uint32_t readAll(uint8_t* buf, uint32_t len) {
+ T_VIRTUAL_CALL();
+ return readAll_virt(buf, len);
+ }
+ virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) {
return apache::thrift::transport::readAll(*this, buf, len);
}
* @param buf The data to write out
* @throws TTransportException if an error occurs
*/
- virtual void write(const uint8_t* /* buf */, uint32_t /* len */) {
- throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot write.");
+ void write(const uint8_t* buf, uint32_t len) {
+ T_VIRTUAL_CALL();
+ write_virt(buf, len);
+ }
+ virtual void write_virt(const uint8_t* /* buf */, uint32_t /* len */) {
+ throw TTransportException(TTransportException::NOT_OPEN,
+ "Base TTransport cannot write.");
}
/**
* the transport's internal buffers.
* @throws TTransportException if an error occurs
*/
- virtual const uint8_t* borrow(uint8_t* /* buf */, uint32_t* /* len */) {
+ const uint8_t* borrow(uint8_t* buf, uint32_t* len) {
+ T_VIRTUAL_CALL();
+ return borrow_virt(buf, len);
+ }
+ virtual const uint8_t* borrow_virt(uint8_t* /* buf */, uint32_t* /* len */) {
return NULL;
}
* @param len How many bytes to consume
* @throws TTransportException If an error occurs
*/
- virtual void consume(uint32_t /* len */) {
- throw TTransportException(TTransportException::NOT_OPEN, "Base TTransport cannot consume.");
+ void consume(uint32_t len) {
+ T_VIRTUAL_CALL();
+ consume_virt(len);
+ }
+ virtual void consume_virt(uint32_t /* len */) {
+ throw TTransportException(TTransportException::NOT_OPEN,
+ "Base TTransport cannot consume.");
}
protected:
* go anywhere.
*
*/
-class TNullTransport : public TTransport {
+class TNullTransport : public TVirtualTransport<TNullTransport> {
public:
TNullTransport() {}
return dstTrans_;
}
+ /*
+ * Override TTransport *_virt() functions to invoke our implementations.
+ * We cannot use TVirtualTransport to provide these, since we need to inherit
+ * virtually from TTransport.
+ */
+ virtual uint32_t read_virt(uint8_t* buf, uint32_t len) {
+ return this->read(buf, len);
+ }
+ virtual void write_virt(const uint8_t* buf, uint32_t len) {
+ this->write(buf, len);
+ }
+
protected:
boost::shared_ptr<TTransport> srcTrans_;
boost::shared_ptr<TTransport> dstTrans_;
void seekToChunk(int32_t chunk);
void seekToEnd();
+ /*
+ * Override TTransport *_virt() functions to invoke our implementations.
+ * We cannot use TVirtualTransport to provide these, since we need to inherit
+ * virtually from TTransport.
+ */
+ virtual uint32_t read_virt(uint8_t* buf, uint32_t len) {
+ return this->read(buf, len);
+ }
+ virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) {
+ return this->readAll(buf, len);
+ }
+ virtual void write_virt(const uint8_t* buf, uint32_t len) {
+ this->write(buf, len);
+ }
+
protected:
// shouldn't be used
TPipedFileReaderTransport();
--- /dev/null
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_
+#define _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_ 1
+
+#include <transport/TTransport.h>
+
+namespace apache { namespace thrift { namespace transport {
+
+
+/**
+ * Helper class that provides default implementations of TTransport methods.
+ *
+ * This class provides default implementations of read(), readAll(), write(),
+ * borrow() and consume().
+ *
+ * In the TTransport base class, each of these methods simply invokes its
+ * virtual counterpart. This class overrides them to always perform the
+ * default behavior, without a virtual function call.
+ *
+ * The primary purpose of this class is to serve as a base class for
+ * TVirtualTransport, and prevent infinite recursion if one of its subclasses
+ * does not override the TTransport implementation of these methods. (Since
+ * TVirtualTransport::read_virt() calls read(), and TTransport::read() calls
+ * read_virt().)
+ */
+class TTransportDefaults : public TTransport {
+ public:
+ /*
+ * TTransport *_virt() methods provide reasonable default implementations.
+ * Invoke them non-virtually.
+ */
+ uint32_t read(uint8_t* buf, uint32_t len) {
+ return this->TTransport::read_virt(buf, len);
+ }
+ uint32_t readAll(uint8_t* buf, uint32_t len) {
+ return this->TTransport::readAll_virt(buf, len);
+ }
+ void write(const uint8_t* buf, uint32_t len) {
+ this->TTransport::write_virt(buf, len);
+ }
+ const uint8_t* borrow(uint8_t* buf, uint32_t* len) {
+ return this->TTransport::borrow_virt(buf, len);
+ }
+ void consume(uint32_t len) {
+ this->TTransport::consume_virt(len);
+ }
+
+ protected:
+ TTransportDefaults() {}
+};
+
+/**
+ * Helper class to provide polymorphism for subclasses of TTransport.
+ *
+ * This class implements *_virt() methods of TTransport, to call the
+ * non-virtual versions of these functions in the proper subclass.
+ *
+ * To define your own transport class using TVirtualTransport:
+ * 1) Derive your subclass from TVirtualTransport<your class>
+ * e.g: class MyTransport : public TVirtualTransport<MyTransport> {
+ * 2) Provide your own implementations of read(), readAll(), etc.
+ * These methods should be non-virtual.
+ *
+ * Transport implementations that need to use virtual inheritance when
+ * inheriting from TTransport cannot use TVirtualTransport.
+ *
+ * @author Chad Walters <chad@powerset.com>
+ */
+template <class Transport_, class Super_=TTransportDefaults>
+class TVirtualTransport : public Super_ {
+ public:
+ /*
+ * Implementations of the *_virt() functions, to call the subclass's
+ * non-virtual implementation function.
+ */
+ virtual uint32_t read_virt(uint8_t* buf, uint32_t len) {
+ return static_cast<Transport_*>(this)->read(buf, len);
+ }
+
+ virtual uint32_t readAll_virt(uint8_t* buf, uint32_t len) {
+ return static_cast<Transport_*>(this)->readAll(buf, len);
+ }
+
+ virtual void write_virt(const uint8_t* buf, uint32_t len) {
+ static_cast<Transport_*>(this)->write(buf, len);
+ }
+
+ virtual const uint8_t* borrow_virt(uint8_t* buf, uint32_t* len) {
+ return static_cast<Transport_*>(this)->borrow(buf, len);
+ }
+
+ virtual void consume_virt(uint32_t len) {
+ static_cast<Transport_*>(this)->consume(len);
+ }
+
+ /*
+ * Provide a default readAll() implementation that invokes
+ * read() non-virtually.
+ *
+ * Note: subclasses that use TVirtualTransport to derive from another
+ * transport implementation (i.e., not TTransportDefaults) should beware that
+ * this may override any non-default readAll() implementation provided by
+ * the parent transport class. They may need to redefine readAll() to call
+ * the correct parent implementation, if desired.
+ */
+ uint32_t readAll(uint8_t* buf, uint32_t len) {
+ Transport_* trans = static_cast<Transport_*>(this);
+ return ::apache::thrift::transport::readAll(*trans, buf, len);
+ }
+
+ protected:
+ TVirtualTransport() {}
+
+ /*
+ * Templatized constructors, to allow arguments to be passed to the Super_
+ * constructor. Currently we only support 0, 1, or 2 arguments, but
+ * additional versions can be added as needed.
+ */
+ template <typename Arg_>
+ TVirtualTransport(Arg_ const& arg) : Super_(arg) { }
+
+ template <typename Arg1_, typename Arg2_>
+ TVirtualTransport(Arg1_ const& a1, Arg2_ const& a2) : Super_(a1, a2) { }
+};
+
+}}} // apache::thrift::transport
+
+#endif // #ifndef _THRIFT_TRANSPORT_TVIRTUALTRANSPORT_H_
#include <boost/lexical_cast.hpp>
#include <transport/TTransport.h>
+#include <transport/TVirtualTransport.h>
struct z_stream_s;
* the underlying transport is TBuffered or TMemory.
*
*/
-class TZlibTransport : public TTransport {
+class TZlibTransport : public TVirtualTransport<TZlibTransport> {
public:
/**