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
diff --git a/lib/cpp/src/qt/TQIODeviceTransport.cpp b/lib/cpp/src/qt/TQIODeviceTransport.cpp
index c5b53a8..4172ed0 100644
--- a/lib/cpp/src/qt/TQIODeviceTransport.cpp
+++ b/lib/cpp/src/qt/TQIODeviceTransport.cpp
@@ -1,155 +1,157 @@
#include "TQIODeviceTransport.h"
+#include <QAbstractSocket>
+#include <QIODevice>
+
#include <transport/TBufferTransports.h>
-#include <QAbstractSocket>
-
-#include <iostream>
-
+using boost::shared_ptr;
+
namespace apache { namespace thrift { namespace transport {
- using boost::shared_ptr;
- TQIODeviceTransport::TQIODeviceTransport(shared_ptr<QIODevice> dev)
- : dev_(dev)
- {
+TQIODeviceTransport::TQIODeviceTransport(shared_ptr<QIODevice> 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;
+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;
}
- if (readSize == 0) {
- // dev_->waitForReadyRead(50);
- } else {
- buf += readSize;
- len -= readSize;
- }
+ // 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<char *>(buf), len);
-
- if (readSize < 0) {
- QAbstractSocket* socket;
- if ((socket = qobject_cast<QAbstractSocket* >(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<const char*>(buf), len);
- if (written < 0) {
- QAbstractSocket* socket;
- if ((socket = qobject_cast<QAbstractSocket*>(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<QAbstractSocket*>(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<char *>(buf), actualSize);
+
+ if (readSize < 0) {
+ QAbstractSocket* socket;
+ if ((socket = qobject_cast<QAbstractSocket* >(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<const char*>(buf), len);
+ if (written < 0) {
+ QAbstractSocket* socket;
+ if ((socket = qobject_cast<QAbstractSocket*>(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<QAbstractSocket*>(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 8ce7c78..5ee8f6d 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 <QIODevice>
-
#include <boost/shared_ptr.hpp>
#include <transport/TVirtualTransport.h>
-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<TQIODeviceTransport> {
- public:
- explicit TQIODeviceTransport(boost::shared_ptr<QIODevice> dev);
- ~TQIODeviceTransport();
+/**
+ * Transport that operates on a QIODevice (socket, file, etc).
+ */
+class TQIODeviceTransport : public apache::thrift::transport::TVirtualTransport<TQIODeviceTransport> {
+ public:
+ explicit TQIODeviceTransport(boost::shared_ptr<QIODevice> 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<QIODevice> dev_;
- };
+ private:
+ TQIODeviceTransport(const TQIODeviceTransport&);
+ TQIODeviceTransport& operator=(const TQIODeviceTransport&);
+
+ boost::shared_ptr<QIODevice> 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 65ad68d..733a3d8 100644
--- a/lib/cpp/src/qt/TQTcpServer.cpp
+++ b/lib/cpp/src/qt/TQTcpServer.cpp
@@ -1,11 +1,13 @@
-#include "TQTcpServer.h"
-#include <protocol/TProtocol.h>
-#include <async/TAsyncProcessor.h>
+#include "TQTcpServer.h"
+#include "TQIODeviceTransport.h"
#include <QTcpSocket>
-#include "TQIODeviceTransport.h"
+#include <tr1/functional>
+
+#include <protocol/TProtocol.h>
+#include <async/TAsyncProcessor.h>
using boost::shared_ptr;
using apache::thrift::protocol::TProtocol;
@@ -91,8 +93,7 @@
QTcpSocket* connection(qobject_cast<QTcpSocket*>(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 @@
QTcpSocket* connection(qobject_cast<QTcpSocket*>(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::finish(shared_ptr<ConnectionContext> 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 82bec39..7838357 100644
--- a/lib/cpp/src/qt/TQTcpServer.h
+++ b/lib/cpp/src/qt/TQTcpServer.h
@@ -6,10 +6,7 @@
#include <boost/shared_ptr.hpp>
-#include <tr1/functional>
-
namespace apache { namespace thrift { namespace protocol {
-class TProtocol;
class TProtocolFactory;
}}} // apache::thrift::protocol
@@ -17,6 +14,11 @@
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 @@
void socketClosed();
private:
+ TQTcpServer(const TQTcpServer&);
+ TQTcpServer& operator=(const TQTcpServer&);
+
class ConnectionContext;
void finish(boost::shared_ptr<ConnectionContext> ctx, bool healthy);