Commit a3d29f51446a7103a2101a21135c5f920aa73dc4

Authored by Wiebe Cazemier
1 parent 4a16d48b

Fix unnecessary QoS packet creation

The extraneous creation would happen when multiple subscribes at
different QoS levels happen.
client.cpp
@@ -251,14 +251,14 @@ void Client::writeMqttPacketAndBlameThisClient(PublishCopyFactory &copyFactory, @@ -251,14 +251,14 @@ void Client::writeMqttPacketAndBlameThisClient(PublishCopyFactory &copyFactory,
251 251
252 MqttPacket *p = copyFactory.getOptimumPacket(max_qos, this->protocolVersion, topic_alias, skip_topic); 252 MqttPacket *p = copyFactory.getOptimumPacket(max_qos, this->protocolVersion, topic_alias, skip_topic);
253 253
254 - assert(p->getQos() <= max_qos); 254 + assert(static_cast<bool>(p->getQos()) == static_cast<bool>(max_qos));
255 255
256 if (p->getQos() > 0) 256 if (p->getQos() > 0)
257 { 257 {
258 // This may change the packet ID and QoS of the incoming packet for each subscriber, but because we don't store that packet anywhere, 258 // This may change the packet ID and QoS of the incoming packet for each subscriber, but because we don't store that packet anywhere,
259 // that should be fine. 259 // that should be fine.
260 p->setPacketId(packet_id); 260 p->setPacketId(packet_id);
261 - p->setQos(max_qos); 261 + p->setQos(copyFactory.getEffectiveQos(max_qos));
262 } 262 }
263 263
264 writeMqttPacketAndBlameThisClient(*p); 264 writeMqttPacketAndBlameThisClient(*p);
publishcopyfactory.cpp
@@ -19,31 +19,32 @@ PublishCopyFactory::PublishCopyFactory(Publish *publish) : @@ -19,31 +19,32 @@ PublishCopyFactory::PublishCopyFactory(Publish *publish) :
19 19
20 MqttPacket *PublishCopyFactory::getOptimumPacket(const char max_qos, const ProtocolVersion protocolVersion, uint16_t topic_alias, bool skip_topic) 20 MqttPacket *PublishCopyFactory::getOptimumPacket(const char max_qos, const ProtocolVersion protocolVersion, uint16_t topic_alias, bool skip_topic)
21 { 21 {
  22 + const char actualQos = getEffectiveQos(max_qos);
  23 +
22 if (packet) 24 if (packet)
23 { 25 {
24 if (protocolVersion >= ProtocolVersion::Mqtt5 && (packet->containsClientSpecificProperties() || topic_alias > 0)) 26 if (protocolVersion >= ProtocolVersion::Mqtt5 && (packet->containsClientSpecificProperties() || topic_alias > 0))
25 { 27 {
26 Publish newPublish(packet->getPublishData()); 28 Publish newPublish(packet->getPublishData());
27 - newPublish.qos = max_qos; 29 + newPublish.qos = actualQos;
28 newPublish.topicAlias = topic_alias; 30 newPublish.topicAlias = topic_alias;
29 newPublish.skipTopic = skip_topic; 31 newPublish.skipTopic = skip_topic;
30 this->oneShotPacket = std::make_unique<MqttPacket>(protocolVersion, newPublish); 32 this->oneShotPacket = std::make_unique<MqttPacket>(protocolVersion, newPublish);
31 return this->oneShotPacket.get(); 33 return this->oneShotPacket.get();
32 } 34 }
33 35
34 - if (packet->getProtocolVersion() == protocolVersion && orgQos == max_qos) 36 + if (packet->getProtocolVersion() == protocolVersion && static_cast<bool>(orgQos) == static_cast<bool>(actualQos))
35 { 37 {
36 - assert(orgQos == packet->getQos());  
37 return packet; 38 return packet;
38 } 39 }
39 40
40 - const int cache_key = (static_cast<uint8_t>(protocolVersion) * 10) + max_qos; 41 + const int cache_key = (static_cast<uint8_t>(protocolVersion) * 10) + actualQos;
41 std::unique_ptr<MqttPacket> &cachedPack = constructedPacketCache[cache_key]; 42 std::unique_ptr<MqttPacket> &cachedPack = constructedPacketCache[cache_key];
42 43
43 if (!cachedPack) 44 if (!cachedPack)
44 { 45 {
45 Publish newPublish(packet->getPublishData()); 46 Publish newPublish(packet->getPublishData());
46 - newPublish.qos = max_qos; 47 + newPublish.qos = actualQos;
47 cachedPack = std::make_unique<MqttPacket>(protocolVersion, newPublish); 48 cachedPack = std::make_unique<MqttPacket>(protocolVersion, newPublish);
48 } 49 }
49 50
@@ -53,7 +54,7 @@ MqttPacket *PublishCopyFactory::getOptimumPacket(const char max_qos, const Proto @@ -53,7 +54,7 @@ MqttPacket *PublishCopyFactory::getOptimumPacket(const char max_qos, const Proto
53 // Getting an instance of a Publish object happens at least on retained messages, will messages and SYS topics. It's low traffic, anyway. 54 // Getting an instance of a Publish object happens at least on retained messages, will messages and SYS topics. It's low traffic, anyway.
54 assert(publish); 55 assert(publish);
55 56
56 - publish->qos = getEffectiveQos(max_qos); 57 + publish->qos = actualQos;
57 58
58 this->oneShotPacket = std::make_unique<MqttPacket>(protocolVersion, *publish); 59 this->oneShotPacket = std::make_unique<MqttPacket>(protocolVersion, *publish);
59 return this->oneShotPacket.get(); 60 return this->oneShotPacket.get();
publishcopyfactory.h
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 * @brief The PublishCopyFactory class is for managing copies of an incoming publish, including sometimes not making copies at all. 11 * @brief The PublishCopyFactory class is for managing copies of an incoming publish, including sometimes not making copies at all.
12 * 12 *
13 * The idea is that certain incoming packets can just be written to the receiving client as-is, without constructing a new one. We do have to change the bytes 13 * The idea is that certain incoming packets can just be written to the receiving client as-is, without constructing a new one. We do have to change the bytes
14 - * where the QoS is stored, so we keep track of the original. 14 + * where the QoS is stored, so we keep track of the original QoS.
15 * 15 *
16 * Ownership info: object of this type are never copied or transferred, so the internal pointers come from (near) the same scope these objects 16 * Ownership info: object of this type are never copied or transferred, so the internal pointers come from (near) the same scope these objects
17 * are created from. 17 * are created from.