add qos support to channel
AMQP Basic qos support added to Channel class. There is an option for global qos which is currently not added. Also, added auto tests for qos definition, proper qos operation and verifying that RabbitMQ does not support prefetchSize.
This commit is contained in:
parent
9bd5610ac7
commit
12a03f959f
|
|
@ -13,6 +13,10 @@ ChannelPrivate::ChannelPrivate(Channel *q)
|
||||||
: channelNumber(0),
|
: channelNumber(0),
|
||||||
opened(false),
|
opened(false),
|
||||||
needOpen(true),
|
needOpen(true),
|
||||||
|
prefetchSize(0),
|
||||||
|
requestedPrefetchSize(0),
|
||||||
|
prefetchCount(0),
|
||||||
|
requestedPrefetchCount(0),
|
||||||
error(QAMQP::NoError),
|
error(QAMQP::NoError),
|
||||||
q_ptr(q)
|
q_ptr(q)
|
||||||
{
|
{
|
||||||
|
|
@ -55,6 +59,15 @@ bool ChannelPrivate::_q_method(const Frame::Method &frame)
|
||||||
if (frame.channel() != channelNumber)
|
if (frame.channel() != channelNumber)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
if (frame.methodClass() == Frame::fcBasic) {
|
||||||
|
if (frame.id() == bmQosOk) {
|
||||||
|
qosOk(frame);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (frame.methodClass() != Frame::fcChannel)
|
if (frame.methodClass() != Frame::fcChannel)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -88,8 +101,12 @@ void ChannelPrivate::_q_open()
|
||||||
|
|
||||||
void ChannelPrivate::sendFrame(const Frame::Base &frame)
|
void ChannelPrivate::sendFrame(const Frame::Base &frame)
|
||||||
{
|
{
|
||||||
if (client)
|
if (!client) {
|
||||||
client->d_func()->sendFrame(frame);
|
qAmqpDebug() << Q_FUNC_INFO << "invalid client";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->d_func()->sendFrame(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelPrivate::open()
|
void ChannelPrivate::open()
|
||||||
|
|
@ -203,20 +220,22 @@ void ChannelPrivate::openOk(const Frame::Method &frame)
|
||||||
q->channelOpened();
|
q->channelOpened();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChannelPrivate::setQOS(qint32 prefetchSize, quint16 prefetchCount)
|
|
||||||
{
|
|
||||||
Q_UNUSED(prefetchSize)
|
|
||||||
Q_UNUSED(prefetchCount)
|
|
||||||
qAmqpDebug() << Q_FUNC_INFO << "temporarily disabled";
|
|
||||||
// client_->d_func()->connection_->d_func()->setQOS(prefetchSize, prefetchCount, channelNumber, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ChannelPrivate::_q_disconnected()
|
void ChannelPrivate::_q_disconnected()
|
||||||
{
|
{
|
||||||
nextChannelNumber = 0;
|
nextChannelNumber = 0;
|
||||||
opened = false;
|
opened = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ChannelPrivate::qosOk(const Frame::Method &frame)
|
||||||
|
{
|
||||||
|
Q_Q(Channel);
|
||||||
|
Q_UNUSED(frame)
|
||||||
|
|
||||||
|
prefetchCount = requestedPrefetchCount;
|
||||||
|
prefetchSize = requestedPrefetchSize;
|
||||||
|
Q_EMIT q->qosDefined();
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Channel::Channel(int channelNumber, Client *client)
|
Channel::Channel(int channelNumber, Client *client)
|
||||||
|
|
@ -276,10 +295,36 @@ bool Channel::isOpened() const
|
||||||
return d->opened;
|
return d->opened;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Channel::setQOS(qint32 prefetchSize, quint16 prefetchCount)
|
void Channel::qos(qint16 prefetchCount, qint32 prefetchSize)
|
||||||
{
|
{
|
||||||
Q_D(Channel);
|
Q_D(Channel);
|
||||||
d->setQOS(prefetchSize, prefetchCount);
|
Frame::Method frame(Frame::fcBasic, ChannelPrivate::bmQos);
|
||||||
|
frame.setChannel(d->channelNumber);
|
||||||
|
|
||||||
|
QByteArray arguments;
|
||||||
|
QDataStream stream(&arguments, QIODevice::WriteOnly);
|
||||||
|
|
||||||
|
d->requestedPrefetchSize = prefetchSize;
|
||||||
|
d->requestedPrefetchCount = prefetchCount;
|
||||||
|
|
||||||
|
stream << qint32(prefetchSize);
|
||||||
|
stream << qint16(prefetchCount);
|
||||||
|
stream << qint8(0x0); // global
|
||||||
|
|
||||||
|
frame.setArguments(arguments);
|
||||||
|
d->sendFrame(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
qint32 Channel::prefetchSize() const
|
||||||
|
{
|
||||||
|
Q_D(const Channel);
|
||||||
|
return d->prefetchSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
qint16 Channel::prefetchCount() const
|
||||||
|
{
|
||||||
|
Q_D(const Channel);
|
||||||
|
return d->prefetchCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
Error Channel::error() const
|
Error Channel::error() const
|
||||||
|
|
|
||||||
|
|
@ -27,16 +27,22 @@ public:
|
||||||
Error error() const;
|
Error error() const;
|
||||||
QString errorString() const;
|
QString errorString() const;
|
||||||
|
|
||||||
|
qint32 prefetchSize() const;
|
||||||
|
qint16 prefetchCount() const;
|
||||||
|
|
||||||
|
// AMQP Basic
|
||||||
|
void qos(qint16 prefetchCount, qint32 prefetchSize = 0);
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
void closeChannel();
|
void closeChannel();
|
||||||
void reopen();
|
void reopen();
|
||||||
void setQOS(qint32 prefetchSize, quint16 prefetchCount);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void opened();
|
void opened();
|
||||||
void closed();
|
void closed();
|
||||||
void flowChanged(bool enabled);
|
void flowChanged(bool enabled);
|
||||||
void error(QAMQP::Error error);
|
void error(QAMQP::Error error);
|
||||||
|
void qosDefined();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void channelOpened() = 0;
|
virtual void channelOpened() = 0;
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,6 @@ public:
|
||||||
void init(int channel, Client *client);
|
void init(int channel, Client *client);
|
||||||
void stateChanged(State state);
|
void stateChanged(State state);
|
||||||
|
|
||||||
void setQOS(qint32 prefetchSize, quint16 prefetchCount);
|
|
||||||
void sendFrame(const Frame::Base &frame);
|
void sendFrame(const Frame::Base &frame);
|
||||||
|
|
||||||
void open();
|
void open();
|
||||||
|
|
@ -65,6 +64,7 @@ public:
|
||||||
void flowOk(const Frame::Method &frame);
|
void flowOk(const Frame::Method &frame);
|
||||||
void close(const Frame::Method &frame);
|
void close(const Frame::Method &frame);
|
||||||
void closeOk(const Frame::Method &frame);
|
void closeOk(const Frame::Method &frame);
|
||||||
|
void qosOk(const Frame::Method &frame);
|
||||||
|
|
||||||
// private slots
|
// private slots
|
||||||
virtual void _q_disconnected();
|
virtual void _q_disconnected();
|
||||||
|
|
@ -77,6 +77,11 @@ public:
|
||||||
bool opened;
|
bool opened;
|
||||||
bool needOpen;
|
bool needOpen;
|
||||||
|
|
||||||
|
qint32 prefetchSize;
|
||||||
|
qint32 requestedPrefetchSize;
|
||||||
|
qint16 prefetchCount;
|
||||||
|
qint16 requestedPrefetchCount;
|
||||||
|
|
||||||
Error error;
|
Error error;
|
||||||
QString errorString;
|
QString errorString;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,9 @@ private Q_SLOTS:
|
||||||
void getEmpty();
|
void getEmpty();
|
||||||
void get();
|
void get();
|
||||||
void verifyContentEncodingIssue33();
|
void verifyContentEncodingIssue33();
|
||||||
|
void defineQos();
|
||||||
|
void invalidQos();
|
||||||
|
void qos();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void declareQueueAndVerifyConsuming(Queue *queue);
|
void declareQueueAndVerifyConsuming(Queue *queue);
|
||||||
|
|
@ -400,5 +403,70 @@ void tst_QAMQPQueue::verifyContentEncodingIssue33()
|
||||||
QCOMPARE(contentType, QLatin1String("fakeContentEncoding"));
|
QCOMPARE(contentType, QLatin1String("fakeContentEncoding"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QAMQPQueue::defineQos()
|
||||||
|
{
|
||||||
|
Queue *queue = client->createQueue("test-define-qos");
|
||||||
|
declareQueueAndVerifyConsuming(queue);
|
||||||
|
|
||||||
|
queue->qos(10);
|
||||||
|
QVERIFY(waitForSignal(queue, SIGNAL(qosDefined())));
|
||||||
|
QCOMPARE(queue->prefetchCount(), qint16(10));
|
||||||
|
QCOMPARE(queue->prefetchSize(), 0);
|
||||||
|
|
||||||
|
// clean up queue
|
||||||
|
queue->remove(Queue::roForce);
|
||||||
|
QVERIFY(waitForSignal(queue, SIGNAL(removed())));
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QAMQPQueue::invalidQos()
|
||||||
|
{
|
||||||
|
Queue *queue = client->createQueue("test-invalid-define-qos");
|
||||||
|
declareQueueAndVerifyConsuming(queue);
|
||||||
|
|
||||||
|
queue->qos(10, 10);
|
||||||
|
QVERIFY(waitForSignal(client.data(), SIGNAL(error(QAMQP::Error))));
|
||||||
|
QCOMPARE(client->error(), QAMQP::NotImplementedError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tst_QAMQPQueue::qos()
|
||||||
|
{
|
||||||
|
Queue *queue = client->createQueue("test-qos");
|
||||||
|
queue->declare();
|
||||||
|
QVERIFY(waitForSignal(queue, SIGNAL(declared())));
|
||||||
|
|
||||||
|
queue->qos(1);
|
||||||
|
QVERIFY(waitForSignal(queue, SIGNAL(qosDefined())));
|
||||||
|
QCOMPARE(queue->prefetchCount(), qint16(1));
|
||||||
|
QCOMPARE(queue->prefetchSize(), 0);
|
||||||
|
|
||||||
|
// load up the queue
|
||||||
|
const int messageCount = 10;
|
||||||
|
Exchange *defaultExchange = client->createExchange();
|
||||||
|
for (int i = 0; i < messageCount; ++i) {
|
||||||
|
QString message = QString("message %1").arg(i);
|
||||||
|
defaultExchange->publish(message, "test-qos");
|
||||||
|
}
|
||||||
|
|
||||||
|
QTest::qWait(100);
|
||||||
|
|
||||||
|
// begin consuming, one at a time
|
||||||
|
QVERIFY(queue->consume());
|
||||||
|
QVERIFY(waitForSignal(queue, SIGNAL(consuming(QString))));
|
||||||
|
|
||||||
|
int messageReceivedCount = 0;
|
||||||
|
while (!queue->isEmpty()) {
|
||||||
|
QString expected = QString("message %1").arg(messageReceivedCount);
|
||||||
|
Message message = queue->dequeue();
|
||||||
|
QCOMPARE(message.payload(), expected.toUtf8());
|
||||||
|
queue->ack(message);
|
||||||
|
messageReceivedCount++;
|
||||||
|
|
||||||
|
if (messageReceivedCount < messageCount)
|
||||||
|
QVERIFY(waitForSignal(queue, SIGNAL(messageReceived())));
|
||||||
|
}
|
||||||
|
|
||||||
|
QCOMPARE(messageReceivedCount, messageCount);
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QAMQPQueue)
|
QTEST_MAIN(tst_QAMQPQueue)
|
||||||
#include "tst_qamqpqueue.moc"
|
#include "tst_qamqpqueue.moc"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue