Skip to content

Commit

Permalink
Fix Qpid when sending long messages (from oslo)
Browse files Browse the repository at this point in the history
This is commit 4f97479ad in oslo-incubator

Qpid has a limitation where it cannot serialize a dict containing a
string greater than 65535 characters. This change alters the Qpid
implementation to JSON encode the dict before sending it, but only if
Qpid would fail to serialize it. This maintains as much backward
compatibility as possible, though long messages will still fail if they
are sent to an older receiver.

The first part of this fix was ported to Grizzly in Ib52e9458a to allow
receiving messages from Havana using the new format. Even though this
change will modify the message format, it will only do it when messages
are longer than 65K which would be broken anyway and could cause serious
bugs like the one linked below.

Fixes bug 1215091

Change-Id: I505b648c3d0e1176ec7a3fc7d1646fa5a5232261
  • Loading branch information
Xavier Queralt committed Sep 5, 2013
1 parent fc4d1f9 commit 2d949c4
Showing 1 changed file with 28 additions and 0 deletions.
28 changes: 28 additions & 0 deletions nova/openstack/common/rpc/impl_qpid.py
Expand Up @@ -31,6 +31,7 @@
from nova.openstack.common.rpc import amqp as rpc_amqp
from nova.openstack.common.rpc import common as rpc_common

qpid_codec = importutils.try_import("qpid.codec010")
qpid_messaging = importutils.try_import("qpid.messaging")
qpid_exceptions = importutils.try_import("qpid.messaging.exceptions")

Expand Down Expand Up @@ -247,8 +248,35 @@ def reconnect(self, session):
"""Re-establish the Sender after a reconnection"""
self.sender = session.sender(self.address)

def _pack_json_msg(self, msg):
"""Qpid cannot serialize dicts containing strings longer than 65535
characters. This function dumps the message content to a JSON
string, which Qpid is able to handle.
:param msg: May be either a Qpid Message object or a bare dict.
:returns: A Qpid Message with its content field JSON encoded.
"""
try:
msg.content = jsonutils.dumps(msg.content)
except AttributeError:
# Need to have a Qpid message so we can set the content_type.
msg = qpid_messaging.Message(jsonutils.dumps(msg))
msg.content_type = JSON_CONTENT_TYPE
return msg

def send(self, msg):
"""Send a message"""
try:
# Check if Qpid can encode the message
check_msg = msg
if not hasattr(check_msg, 'content_type'):
check_msg = qpid_messaging.Message(msg)
content_type = check_msg.content_type
enc, dec = qpid_messaging.message.get_codec(content_type)
enc(check_msg.content)
except qpid_codec.CodecException:
# This means the message couldn't be serialized as a dict.
msg = self._pack_json_msg(msg)
self.sender.send(msg)


Expand Down

0 comments on commit 2d949c4

Please sign in to comment.