From 19a991528f8ed41319737ee758b79ae8b66cd9f7 Mon Sep 17 00:00:00 2001 From: Roger Meier Date: Sat, 11 Feb 2012 19:09:30 +0000 Subject: [PATCH] THRIFT-1348 C++ Qt bindings Patch: Doug Rosvick qt-cleanup.patch applied git-svn-id: https://svn.apache.org/repos/asf/thrift/trunk@1243124 13f79535-47bb-0310-9956-ffa450edef68 --- lib/cpp/src/qt/TQIODeviceTransport.cpp | 268 +++++++++++++------------ lib/cpp/src/qt/TQIODeviceTransport.h | 53 +++-- lib/cpp/src/qt/TQTcpServer.cpp | 19 +- lib/cpp/src/qt/TQTcpServer.h | 11 +- 4 files changed, 177 insertions(+), 174 deletions(-) diff --git a/lib/cpp/src/qt/TQIODeviceTransport.cpp b/lib/cpp/src/qt/TQIODeviceTransport.cpp index c5b53a8f2..4172ed098 100644 --- a/lib/cpp/src/qt/TQIODeviceTransport.cpp +++ b/lib/cpp/src/qt/TQIODeviceTransport.cpp @@ -1,155 +1,157 @@ #include "TQIODeviceTransport.h" +#include +#include + #include -#include - -#include - +using boost::shared_ptr; + namespace apache { namespace thrift { namespace transport { - using boost::shared_ptr; - TQIODeviceTransport::TQIODeviceTransport(shared_ptr dev) - : dev_(dev) - { +TQIODeviceTransport::TQIODeviceTransport(shared_ptr dev) + : dev_(dev) +{ +} + +TQIODeviceTransport::~TQIODeviceTransport() +{ + dev_->close(); +} + +void TQIODeviceTransport::open() +{ + if (!isOpen()) { + throw TTransportException(TTransportException::NOT_OPEN, + "open(): underlying QIODevice isn't open"); } +} - TQIODeviceTransport::~TQIODeviceTransport() - { - dev_->close(); - } +bool TQIODeviceTransport::isOpen() +{ + return dev_->isOpen(); +} - void TQIODeviceTransport::open() - { - if (!isOpen()) { - throw TTransportException(TTransportException::NOT_OPEN, - "open(): underlying QIODevice isn't open"); - } - } +bool TQIODeviceTransport::peek() +{ + return dev_->bytesAvailable() > 0; +} - bool TQIODeviceTransport::isOpen() - { - return dev_->isOpen(); - } +void TQIODeviceTransport::close() +{ + dev_->close(); +} - bool TQIODeviceTransport::peek() - { - return dev_->bytesAvailable() > 0; - } - - void TQIODeviceTransport::close() - { - dev_->close(); - } - - uint32_t TQIODeviceTransport::readAll(uint8_t* buf, uint32_t len) { - uint32_t requestLen = len; - while (len) { - uint32_t readSize; - try { - readSize = read(buf, len); - } catch (...) { - if (len != requestLen) { - // something read already - return requestLen - len; - } - // error but nothing read yet - throw; - } - if (readSize == 0) { - // dev_->waitForReadyRead(50); - } else { - buf += readSize; - len -= readSize; +uint32_t TQIODeviceTransport::readAll(uint8_t* buf, uint32_t len) +{ + uint32_t requestLen = len; + while (len) { + uint32_t readSize; + try { + readSize = read(buf, len); + } catch (...) { + if (len != requestLen) { + // something read already + return requestLen - len; } + // error but nothing read yet + throw; } - return requestLen; - } - - uint32_t TQIODeviceTransport::read(uint8_t* buf, uint32_t len) - { - uint32_t actualSize; - qint64 readSize; - - if (!dev_->isOpen()) { - throw TTransportException(TTransportException::NOT_OPEN, - "read(): underlying QIODevice is not open"); - } - - actualSize = (uint32_t)std::min((qint64)len, dev_->bytesAvailable()); - readSize = dev_->read(reinterpret_cast(buf), len); - - if (readSize < 0) { - QAbstractSocket* socket; - if ((socket = qobject_cast(dev_.get()))) { - throw TTransportException(TTransportException::UNKNOWN, - "Failed to read() from QAbstractSocket", - socket->error()); - } - throw TTransportException(TTransportException::UNKNOWN, - "Failed to read from from QIODevice"); - } - - return (uint32_t)readSize; - } - - void TQIODeviceTransport::write(const uint8_t* buf, uint32_t len) - { - while (len) { - uint32_t written = write_partial(buf, len); - len -= written; - // dev_->waitForBytesWritten(50); - } - } - - uint32_t TQIODeviceTransport::write_partial(const uint8_t* buf, uint32_t len) - { - qint64 written; - - if (!dev_->isOpen()) { - throw TTransportException(TTransportException::NOT_OPEN, - "write_partial(): underlying QIODevice is not open"); - } - - written = dev_->write(reinterpret_cast(buf), len); - if (written < 0) { - QAbstractSocket* socket; - if ((socket = qobject_cast(dev_.get()))) { - throw TTransportException(TTransportException::UNKNOWN, - "write_partial(): failed to write to QAbstractSocket", socket->error()); - } - - throw TTransportException(TTransportException::UNKNOWN, - "write_partial(): failed to write to underlying QIODevice"); - } - - return (uint32_t)written; - } - - void TQIODeviceTransport::flush() - { - if (!dev_->isOpen()) { - throw TTransportException(TTransportException::NOT_OPEN, - "flush(): underlying QIODevice is not open"); - } - - QAbstractSocket* socket; - - if ((socket = qobject_cast(dev_.get()))) { - socket->flush(); + if (readSize == 0) { + dev_->waitForReadyRead(50); } else { - dev_->waitForBytesWritten(1); + buf += readSize; + len -= readSize; } } + return requestLen; +} - uint8_t* TQIODeviceTransport::borrow(uint8_t* buf, uint32_t* len) - { - return NULL; +uint32_t TQIODeviceTransport::read(uint8_t* buf, uint32_t len) +{ + uint32_t actualSize; + qint64 readSize; + + if (!dev_->isOpen()) { + throw TTransportException(TTransportException::NOT_OPEN, + "read(): underlying QIODevice is not open"); } - void TQIODeviceTransport::consume(uint32_t len) - { - throw TTransportException(TTransportException::UNKNOWN); + actualSize = (uint32_t)std::min((qint64)len, dev_->bytesAvailable()); + readSize = dev_->read(reinterpret_cast(buf), actualSize); + + if (readSize < 0) { + QAbstractSocket* socket; + if ((socket = qobject_cast(dev_.get()))) { + throw TTransportException(TTransportException::UNKNOWN, + "Failed to read() from QAbstractSocket", + socket->error()); + } + throw TTransportException(TTransportException::UNKNOWN, + "Failed to read from from QIODevice"); } + + return (uint32_t)readSize; +} + +void TQIODeviceTransport::write(const uint8_t* buf, uint32_t len) +{ + while (len) { + uint32_t written = write_partial(buf, len); + len -= written; + dev_->waitForBytesWritten(50); + } +} + +uint32_t TQIODeviceTransport::write_partial(const uint8_t* buf, uint32_t len) +{ + qint64 written; + + if (!dev_->isOpen()) { + throw TTransportException(TTransportException::NOT_OPEN, + "write_partial(): underlying QIODevice is not open"); + } + + written = dev_->write(reinterpret_cast(buf), len); + if (written < 0) { + QAbstractSocket* socket; + if ((socket = qobject_cast(dev_.get()))) { + throw TTransportException(TTransportException::UNKNOWN, + "write_partial(): failed to write to QAbstractSocket", socket->error()); + } + + throw TTransportException(TTransportException::UNKNOWN, + "write_partial(): failed to write to underlying QIODevice"); + } + + return (uint32_t)written; +} + +void TQIODeviceTransport::flush() +{ + if (!dev_->isOpen()) { + throw TTransportException(TTransportException::NOT_OPEN, + "flush(): underlying QIODevice is not open"); + } + + QAbstractSocket* socket; + + if ((socket = qobject_cast(dev_.get()))) { + socket->flush(); + } else { + dev_->waitForBytesWritten(1); + } +} + +uint8_t* TQIODeviceTransport::borrow(uint8_t* buf, uint32_t* len) +{ + return NULL; +} + +void TQIODeviceTransport::consume(uint32_t len) +{ + throw TTransportException(TTransportException::UNKNOWN); +} + }}} // apache::thrift::transport diff --git a/lib/cpp/src/qt/TQIODeviceTransport.h b/lib/cpp/src/qt/TQIODeviceTransport.h index 8ce7c782b..5ee8f6d5e 100644 --- a/lib/cpp/src/qt/TQIODeviceTransport.h +++ b/lib/cpp/src/qt/TQIODeviceTransport.h @@ -1,47 +1,44 @@ #ifndef _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_ #define _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_ 1 -#include - #include #include -namespace apache { namespace thrift { namespace protocol { -class TProtocol; -}}} // apache::thrift::protocol +class QIODevice; namespace apache { namespace thrift { namespace transport { - class TQIODeviceTransport : public apache::thrift::transport::TVirtualTransport { - public: - explicit TQIODeviceTransport(boost::shared_ptr dev); - ~TQIODeviceTransport(); +/** + * Transport that operates on a QIODevice (socket, file, etc). + */ +class TQIODeviceTransport : public apache::thrift::transport::TVirtualTransport { + public: + explicit TQIODeviceTransport(boost::shared_ptr dev); + virtual ~TQIODeviceTransport(); - void open(); + void open(); + bool isOpen(); + bool peek(); + void close(); - bool isOpen(); - - bool peek(); - - void close(); - - uint32_t readAll(uint8_t *buf, uint32_t len); + uint32_t readAll(uint8_t *buf, uint32_t len); + uint32_t read(uint8_t* buf, uint32_t len); - uint32_t read(uint8_t* buf, uint32_t len); + void write(const uint8_t* buf, uint32_t len); + uint32_t write_partial(const uint8_t* buf, uint32_t len); - void write(const uint8_t* buf, uint32_t len); + void flush(); - uint32_t write_partial(const uint8_t* buf, uint32_t len); + uint8_t* borrow(uint8_t* buf, uint32_t* len); + void consume(uint32_t len); - void flush(); - - uint8_t* borrow(uint8_t* buf, uint32_t* len); - void consume(uint32_t len); - - private: - boost::shared_ptr dev_; - }; + private: + TQIODeviceTransport(const TQIODeviceTransport&); + TQIODeviceTransport& operator=(const TQIODeviceTransport&); + + boost::shared_ptr dev_; +}; }}} // apache::thrift::transport #endif // #ifndef _THRIFT_ASYNC_TQIODEVICE_TRANSPORT_H_ diff --git a/lib/cpp/src/qt/TQTcpServer.cpp b/lib/cpp/src/qt/TQTcpServer.cpp index 65ad68dc6..733a3d810 100644 --- a/lib/cpp/src/qt/TQTcpServer.cpp +++ b/lib/cpp/src/qt/TQTcpServer.cpp @@ -1,11 +1,13 @@ -#include "TQTcpServer.h" -#include -#include +#include "TQTcpServer.h" +#include "TQIODeviceTransport.h" #include -#include "TQIODeviceTransport.h" +#include + +#include +#include using boost::shared_ptr; using apache::thrift::protocol::TProtocol; @@ -91,8 +93,7 @@ void TQTcpServer::beginDecode() QTcpSocket* connection(qobject_cast(sender())); Q_ASSERT(connection); - if (ctxMap_.find(connection) == ctxMap_.end()) - { + if (ctxMap_.find(connection) == ctxMap_.end()) { qWarning("[TQTcpServer] Got data on an unknown QTcpSocket"); return; } @@ -119,8 +120,7 @@ void TQTcpServer::socketClosed() QTcpSocket* connection(qobject_cast(sender())); Q_ASSERT(connection); - if (ctxMap_.find(connection) == ctxMap_.end()) - { + if (ctxMap_.find(connection) == ctxMap_.end()) { qWarning("[TQTcpServer] Unknown QTcpSocket closed"); return; } @@ -130,8 +130,7 @@ void TQTcpServer::socketClosed() void TQTcpServer::finish(shared_ptr ctx, bool healthy) { - if (!healthy) - { + if (!healthy) { qWarning("[TQTcpServer] Processor failed to process data successfully"); ctxMap_.erase(ctx->connection_.get()); } diff --git a/lib/cpp/src/qt/TQTcpServer.h b/lib/cpp/src/qt/TQTcpServer.h index 82bec399b..783835759 100644 --- a/lib/cpp/src/qt/TQTcpServer.h +++ b/lib/cpp/src/qt/TQTcpServer.h @@ -6,10 +6,7 @@ #include -#include - namespace apache { namespace thrift { namespace protocol { -class TProtocol; class TProtocolFactory; }}} // apache::thrift::protocol @@ -17,6 +14,11 @@ namespace apache { namespace thrift { namespace async { class TAsyncProcessor; +/** + * Server that uses Qt to listen for connections. + * Simply give it a QTcpServer that is listening, along with an async + * processor and a protocol factory, and then run the Qt event loop. + */ class TQTcpServer : public QObject { Q_OBJECT public: @@ -32,6 +34,9 @@ class TQTcpServer : public QObject { void socketClosed(); private: + TQTcpServer(const TQTcpServer&); + TQTcpServer& operator=(const TQTcpServer&); + class ConnectionContext; void finish(boost::shared_ptr ctx, bool healthy);