provide access to tuning variables, add checks for frameMax per spec in a number of areas,
add an incomplete autotest for using connection tuning parameters
This commit is contained in:
parent
223af56683
commit
1510e1f6c6
|
|
@ -16,15 +16,15 @@
|
||||||
using namespace QAMQP;
|
using namespace QAMQP;
|
||||||
|
|
||||||
ClientPrivate::ClientPrivate(Client *q)
|
ClientPrivate::ClientPrivate(Client *q)
|
||||||
: port(AMQPPORT),
|
: port(AMQP_PORT),
|
||||||
host(QString::fromLatin1(AMQPHOST)),
|
host(QString::fromLatin1(AMQP_HOST)),
|
||||||
virtualHost(QString::fromLatin1(AMQPVHOST)),
|
virtualHost(QString::fromLatin1(AMQP_VHOST)),
|
||||||
socket(0),
|
socket(0),
|
||||||
closed(false),
|
closed(false),
|
||||||
connected(false),
|
connected(false),
|
||||||
channelMax(0),
|
channelMax(0),
|
||||||
heartbeatDelay(0),
|
heartbeatDelay(0),
|
||||||
frameMax(0),
|
frameMax(AMQP_FRAME_MAX),
|
||||||
error(Client::NoError),
|
error(Client::NoError),
|
||||||
q_ptr(q)
|
q_ptr(q)
|
||||||
{
|
{
|
||||||
|
|
@ -42,7 +42,7 @@ void ClientPrivate::init(const QUrl &connectionString)
|
||||||
QObject::connect(heartbeatTimer, SIGNAL(timeout()), q, SLOT(_q_heartbeat()));
|
QObject::connect(heartbeatTimer, SIGNAL(timeout()), q, SLOT(_q_heartbeat()));
|
||||||
|
|
||||||
authenticator = QSharedPointer<Authenticator>(
|
authenticator = QSharedPointer<Authenticator>(
|
||||||
new AMQPlainAuthenticator(QString::fromLatin1(AMQPLOGIN), QString::fromLatin1(AMQPPSWD)));
|
new AMQPlainAuthenticator(QString::fromLatin1(AMQP_LOGIN), QString::fromLatin1(AMQP_PSWD)));
|
||||||
|
|
||||||
if (connectionString.isValid()) {
|
if (connectionString.isValid()) {
|
||||||
parseConnectionString(connectionString);
|
parseConnectionString(connectionString);
|
||||||
|
|
@ -63,15 +63,15 @@ void ClientPrivate::initSocket()
|
||||||
void ClientPrivate::parseConnectionString(const QUrl &connectionString)
|
void ClientPrivate::parseConnectionString(const QUrl &connectionString)
|
||||||
{
|
{
|
||||||
Q_Q(Client);
|
Q_Q(Client);
|
||||||
if (connectionString.scheme() != AMQPSCHEME &&
|
if (connectionString.scheme() != AMQP_SCHEME &&
|
||||||
connectionString.scheme() != AMQPSSCHEME) {
|
connectionString.scheme() != AMQP_SSCHEME) {
|
||||||
qAmqpDebug() << Q_FUNC_INFO << "invalid scheme: " << connectionString.scheme();
|
qAmqpDebug() << Q_FUNC_INFO << "invalid scheme: " << connectionString.scheme();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
q->setPassword(connectionString.password());
|
q->setPassword(connectionString.password());
|
||||||
q->setUsername(connectionString.userName());
|
q->setUsername(connectionString.userName());
|
||||||
q->setPort(connectionString.port(AMQPPORT));
|
q->setPort(connectionString.port(AMQP_PORT));
|
||||||
q->setHost(connectionString.host());
|
q->setHost(connectionString.host());
|
||||||
q->setVirtualHost(connectionString.path());
|
q->setVirtualHost(connectionString.path());
|
||||||
}
|
}
|
||||||
|
|
@ -156,7 +156,8 @@ void ClientPrivate::_q_readyRead()
|
||||||
const quint8 magic = *(quint8*)&bufferData[Frame::HEADER_SIZE + payloadSize];
|
const quint8 magic = *(quint8*)&bufferData[Frame::HEADER_SIZE + payloadSize];
|
||||||
if (magic != Frame::FRAME_END) {
|
if (magic != Frame::FRAME_END) {
|
||||||
qAmqpDebug() << Q_FUNC_INFO << "FATAL: wrong end of frame";
|
qAmqpDebug() << Q_FUNC_INFO << "FATAL: wrong end of frame";
|
||||||
_q_disconnect();
|
buffer.clear();
|
||||||
|
socket->close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,6 +166,11 @@ void ClientPrivate::_q_readyRead()
|
||||||
case Frame::ftMethod:
|
case Frame::ftMethod:
|
||||||
{
|
{
|
||||||
Frame::Method frame(streamB);
|
Frame::Method frame(streamB);
|
||||||
|
if (frame.size() > frameMax) {
|
||||||
|
close(Client::FrameError, "frame size too large");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (frame.methodClass() == Frame::fcConnection) {
|
if (frame.methodClass() == Frame::fcConnection) {
|
||||||
_q_method(frame);
|
_q_method(frame);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -176,6 +182,11 @@ void ClientPrivate::_q_readyRead()
|
||||||
case Frame::ftHeader:
|
case Frame::ftHeader:
|
||||||
{
|
{
|
||||||
Frame::Content frame(streamB);
|
Frame::Content frame(streamB);
|
||||||
|
if (frame.size() > frameMax) {
|
||||||
|
close(Client::FrameError, "frame size too large");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Frame::ContentHandler *methodHandler, contentHandlerByChannel[frame.channel()])
|
foreach (Frame::ContentHandler *methodHandler, contentHandlerByChannel[frame.channel()])
|
||||||
methodHandler->_q_content(frame);
|
methodHandler->_q_content(frame);
|
||||||
}
|
}
|
||||||
|
|
@ -183,6 +194,11 @@ void ClientPrivate::_q_readyRead()
|
||||||
case Frame::ftBody:
|
case Frame::ftBody:
|
||||||
{
|
{
|
||||||
Frame::ContentBody frame(streamB);
|
Frame::ContentBody frame(streamB);
|
||||||
|
if (frame.size() > frameMax) {
|
||||||
|
close(Client::FrameError, "frame size too large");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (Frame::ContentBodyHandler *methodHandler, bodyHandlersByChannel[frame.channel()])
|
foreach (Frame::ContentBodyHandler *methodHandler, bodyHandlersByChannel[frame.channel()])
|
||||||
methodHandler->_q_body(frame);
|
methodHandler->_q_body(frame);
|
||||||
}
|
}
|
||||||
|
|
@ -295,9 +311,17 @@ void ClientPrivate::tune(const Frame::Method &frame)
|
||||||
QByteArray data = frame.arguments();
|
QByteArray data = frame.arguments();
|
||||||
QDataStream stream(&data, QIODevice::ReadOnly);
|
QDataStream stream(&data, QIODevice::ReadOnly);
|
||||||
|
|
||||||
stream >> channelMax;
|
qint16 channel_max = 0,
|
||||||
stream >> frameMax;
|
heartbeat_delay = 0;
|
||||||
stream >> heartbeatDelay;
|
qint32 frame_max = 0;
|
||||||
|
|
||||||
|
stream >> channel_max;
|
||||||
|
stream >> frame_max;
|
||||||
|
stream >> heartbeat_delay;
|
||||||
|
|
||||||
|
channelMax = qMax(channel_max, channelMax);
|
||||||
|
heartbeatDelay = qMax(heartbeat_delay, heartbeatDelay);
|
||||||
|
frameMax = qMax(frame_max, frameMax);
|
||||||
|
|
||||||
qAmqpDebug(">> channel_max: %d", channelMax);
|
qAmqpDebug(">> channel_max: %d", channelMax);
|
||||||
qAmqpDebug(">> frame_max: %d", frameMax);
|
qAmqpDebug(">> frame_max: %d", frameMax);
|
||||||
|
|
@ -395,7 +419,7 @@ void ClientPrivate::tuneOk()
|
||||||
|
|
||||||
stream << qint16(channelMax);
|
stream << qint16(channelMax);
|
||||||
stream << qint32(frameMax);
|
stream << qint32(frameMax);
|
||||||
stream << qint16(heartbeatTimer->interval() / 1000);
|
stream << qint16(heartbeatDelay / 1000);
|
||||||
|
|
||||||
frame.setArguments(arguments);
|
frame.setArguments(arguments);
|
||||||
sendFrame(frame);
|
sendFrame(frame);
|
||||||
|
|
@ -619,6 +643,58 @@ void Client::setAutoReconnect(bool value)
|
||||||
d->autoReconnect = value;
|
d->autoReconnect = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qint16 Client::channelMax() const
|
||||||
|
{
|
||||||
|
Q_D(const Client);
|
||||||
|
return d->channelMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::setChannelMax(qint16 channelMax)
|
||||||
|
{
|
||||||
|
Q_D(Client);
|
||||||
|
if (d->connected) {
|
||||||
|
qAmqpDebug() << Q_FUNC_INFO << "can't modify value while connected";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->channelMax = channelMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint32 Client::frameMax() const
|
||||||
|
{
|
||||||
|
Q_D(const Client);
|
||||||
|
return d->frameMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::setFrameMax(qint32 frameMax)
|
||||||
|
{
|
||||||
|
Q_D(Client);
|
||||||
|
if (d->connected) {
|
||||||
|
qAmqpDebug() << Q_FUNC_INFO << "can't modify value while connected";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->frameMax = qMax(frameMax, AMQP_FRAME_MIN_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
qint16 Client::heartbeatDelay() const
|
||||||
|
{
|
||||||
|
Q_D(const Client);
|
||||||
|
return d->heartbeatDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::setHeartbeatDelay(qint16 delay)
|
||||||
|
{
|
||||||
|
Q_D(Client);
|
||||||
|
if (d->connected) {
|
||||||
|
qAmqpDebug() << Q_FUNC_INFO << "can't modify value while connected";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->heartbeatDelay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Client::addCustomProperty(const QString &name, const QString &value)
|
void Client::addCustomProperty(const QString &name, const QString &value)
|
||||||
{
|
{
|
||||||
Q_D(Client);
|
Q_D(Client);
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,9 @@ class QAMQP_EXPORT Client : public QObject
|
||||||
Q_PROPERTY(QString user READ username WRITE setUsername)
|
Q_PROPERTY(QString user READ username WRITE setUsername)
|
||||||
Q_PROPERTY(QString password READ password WRITE setPassword)
|
Q_PROPERTY(QString password READ password WRITE setPassword)
|
||||||
Q_PROPERTY(bool autoReconnect READ autoReconnect WRITE setAutoReconnect)
|
Q_PROPERTY(bool autoReconnect READ autoReconnect WRITE setAutoReconnect)
|
||||||
|
Q_PROPERTY(qint16 channelMax READ channelMax WRITE setChannelMax)
|
||||||
|
Q_PROPERTY(qint32 frameMax READ frameMax WRITE setFrameMax)
|
||||||
|
Q_PROPERTY(qint16 heartbeatDelay READ heartbeatDelay() WRITE setHeartbeatDelay)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Client(QObject *parent = 0);
|
Client(QObject *parent = 0);
|
||||||
|
|
@ -58,6 +61,15 @@ public:
|
||||||
|
|
||||||
bool isConnected() const;
|
bool isConnected() const;
|
||||||
|
|
||||||
|
qint16 channelMax() const;
|
||||||
|
void setChannelMax(qint16 channelMax);
|
||||||
|
|
||||||
|
qint32 frameMax() const;
|
||||||
|
void setFrameMax(qint32 frameMax);
|
||||||
|
|
||||||
|
qint16 heartbeatDelay() const;
|
||||||
|
void setHeartbeatDelay(qint16 delay);
|
||||||
|
|
||||||
void addCustomProperty(const QString &name, const QString &value);
|
void addCustomProperty(const QString &name, const QString &value);
|
||||||
QString customProperty(const QString &name) const;
|
QString customProperty(const QString &name) const;
|
||||||
|
|
||||||
|
|
@ -87,7 +99,7 @@ public:
|
||||||
|
|
||||||
// methods
|
// methods
|
||||||
void connectToHost(const QString &connectionString = QString());
|
void connectToHost(const QString &connectionString = QString());
|
||||||
void connectToHost(const QHostAddress &address, quint16 port = AMQPPORT);
|
void connectToHost(const QHostAddress &address, quint16 port = AMQP_PORT);
|
||||||
void disconnectFromHost();
|
void disconnectFromHost();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "amqp_exchange_p.h"
|
#include "amqp_exchange_p.h"
|
||||||
#include "amqp_queue.h"
|
#include "amqp_queue.h"
|
||||||
#include "amqp_global.h"
|
#include "amqp_global.h"
|
||||||
|
#include "amqp_client.h"
|
||||||
|
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
@ -169,13 +170,13 @@ void Exchange::remove(bool ifUnused, bool noWait)
|
||||||
QByteArray arguments;
|
QByteArray arguments;
|
||||||
QDataStream stream(&arguments, QIODevice::WriteOnly);
|
QDataStream stream(&arguments, QIODevice::WriteOnly);
|
||||||
|
|
||||||
stream << qint16(0); //reserver 1
|
stream << qint16(0); //reserved 1
|
||||||
Frame::writeField('s', stream, d->name);
|
Frame::writeField('s', stream, d->name);
|
||||||
|
|
||||||
qint8 flag = 0;
|
qint8 flag = 0;
|
||||||
flag |= (ifUnused ? 0x1 : 0);
|
flag |= (ifUnused ? 0x1 : 0);
|
||||||
flag |= (noWait ? 0x2 : 0);
|
flag |= (noWait ? 0x2 : 0);
|
||||||
stream << flag; //reserver 1
|
stream << flag; //reserved 1
|
||||||
|
|
||||||
frame.setArguments(arguments);
|
frame.setArguments(arguments);
|
||||||
d->sendFrame(frame);
|
d->sendFrame(frame);
|
||||||
|
|
@ -227,9 +228,9 @@ void Exchange::publish(const QString &key, const QByteArray &message,
|
||||||
d->sendFrame(content);
|
d->sendFrame(content);
|
||||||
|
|
||||||
int fullSize = message.size();
|
int fullSize = message.size();
|
||||||
for (int sent = 0; sent < fullSize; sent += (FRAME_MAX - 7)) {
|
for (int sent = 0; sent < fullSize; sent += (d->client->frameMax() - 7)) {
|
||||||
Frame::ContentBody body;
|
Frame::ContentBody body;
|
||||||
QByteArray partition = message.mid(sent, (FRAME_MAX - 7));
|
QByteArray partition = message.mid(sent, (d->client->frameMax() - 7));
|
||||||
body.setChannel(d->channelNumber);
|
body.setChannel(d->channelNumber);
|
||||||
body.setBody(partition);
|
body.setBody(partition);
|
||||||
d->sendFrame(body);
|
d->sendFrame(body);
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ private Q_SLOTS:
|
||||||
void connectDisconnect();
|
void connectDisconnect();
|
||||||
void invalidAuthenticationMechanism();
|
void invalidAuthenticationMechanism();
|
||||||
|
|
||||||
|
void tune();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void autoReconnect();
|
void autoReconnect();
|
||||||
|
|
||||||
|
|
@ -67,5 +69,26 @@ void tst_QAMQPClient::autoReconnect()
|
||||||
QVERIFY(waitForSignal(&client, SIGNAL(connected()), 2));
|
QVERIFY(waitForSignal(&client, SIGNAL(connected()), 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QAMQPClient::tune()
|
||||||
|
{
|
||||||
|
// NOTE: this is totally incomplete, but the framework is here to
|
||||||
|
// test it. currently, only channel_max matters since the default
|
||||||
|
// from rabbit is 0.
|
||||||
|
|
||||||
|
Client client;
|
||||||
|
client.setChannelMax(15);
|
||||||
|
client.setFrameMax(1000);
|
||||||
|
client.setHeartbeatDelay(600);
|
||||||
|
|
||||||
|
client.connectToHost();
|
||||||
|
QVERIFY(waitForSignal(&client, SIGNAL(connected())));
|
||||||
|
QCOMPARE((int)client.channelMax(), 15);
|
||||||
|
QCOMPARE((int)client.heartbeatDelay(), 600);
|
||||||
|
QCOMPARE((int)client.frameMax(), 131072);
|
||||||
|
|
||||||
|
client.disconnectFromHost();
|
||||||
|
QVERIFY(waitForSignal(&client, SIGNAL(disconnected())));
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QAMQPClient)
|
QTEST_MAIN(tst_QAMQPClient)
|
||||||
#include "tst_qamqpclient.moc"
|
#include "tst_qamqpclient.moc"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue