123456789_123456789_123456789_123456789_123456789_

Class: Mongo::Protocol::Compressed

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Message
Instance Chain:
Inherits: Mongo::Protocol::Message
Defined in: lib/mongo/protocol/compressed.rb

Overview

MongoDB Wire protocol Compressed message.

This is a bi-directional message that compresses another opcode. See github.com/mongodb/specifications/blob/master/source/compression/OP_COMPRESSED.rst

Since:

  • 2.5.0

Constant Summary

Serializers - Included

HEADER_PACK, INT32_PACK, INT64_PACK, NULL, ZERO

Message - Inherited

BATCH_SIZE, COLLECTION, LIMIT, MAX_MESSAGE_SIZE, ORDERED, Q

Class Method Summary

Message - Inherited

.deserialize

Deserializes messages from an IO stream.

.new

:nodoc:

.deserialize_array

Deserializes an array of fields in a message.

.deserialize_field

Deserializes a single field in a message.

.deserialize_header

Deserializes the header of the message.

.field

A method for declaring a message field.

.fields

A class method for getting the fields for a message class.

Instance Attribute Summary

Message - Inherited

#replyable?

The default for messages is not to require a reply after sending a message to the server.

#request_id

Returns the request id for the message.

Instance Method Summary

Message - Inherited

#==

Tests for equality between two wire protocol messages by comparing class and field values.

#eql?

Alias for Message#==.

#hash

Creates a hash from the values of the fields of a message.

#maybe_add_server_api,
#maybe_compress

Compress the message, if supported by the wire protocol used and if the command being sent permits compression.

#maybe_decrypt

Possibly decrypt this message with libmongocrypt.

#maybe_encrypt

Possibly encrypt this message with libmongocrypt.

#maybe_inflate

Inflate a message if it is compressed.

#number_returned

Default number returned value for protocol messages.

#serialize

Serializes message into bytes that can be sent on the wire.

#set_request_id

Generates a request id for a message.

#to_s
#compress_if_possible

Compress the message, if the command being sent permits compression.

#fields

A method for getting the fields for a message class.

#merge_sections,
#serialize_fields

Serializes message fields into a buffer.

#serialize_header

Serializes the header of the message consisting of 4 32bit integers.

Constructor Details

.new(message, compressor, zlib_compression_level = nil) ⇒ Compressed

Creates a new OP_COMPRESSED message.

Examples:

Create an OP_COMPRESSED message.

Compressed.new(original_message, 'zlib')

Parameters:

  • message (Mongo::Protocol::Message)

    The original message.

  • compressor (String, Symbol)

    The compression algorithm to use.

  • zlib_compression_level (Integer) (defaults to: nil)

    The zlib compression level to use. -1 and nil imply default.

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/protocol/compressed.rb', line 79

def initialize(message, compressor, zlib_compression_level = nil)
  @original_message = message
  @original_op_code = message.op_code
  @uncompressed_size = 0
  @compressor_id = COMPRESSOR_ID_MAP[compressor]
  @compressed_message = ''
  @zlib_compression_level = zlib_compression_level if zlib_compression_level && zlib_compression_level != -1
  @request_id = message.request_id
end

Instance Attribute Details

#compressed_messageString (rw, private)

Returns:

  • (String)

    The actual compressed message bytes.

[ GitHub ]

  
# File 'lib/mongo/protocol/compressed.rb', line 146

field :compressed_message, Bytes

#compressor_idString (rw, private)

Returns:

  • (String)

    The id of the compressor as a single byte.

[ GitHub ]

  
# File 'lib/mongo/protocol/compressed.rb', line 142

field :compressor_id, Byte

#original_op_code (rw, private)

Field representing the original message’s op code as an Int32.

[ GitHub ]

  
# File 'lib/mongo/protocol/compressed.rb', line 134

field :original_op_code, Int32

#replyable?true, false (readonly)

Whether the message expects a reply from the database.

Examples:

Does the message require a reply?

message.replyable?

Returns:

  • (true, false)

    If the message expects a reply.

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/protocol/compressed.rb', line 120

def replyable?
  @original_message.replyable?
end

#uncompressed_sizeFixnum (rw, private)

Returns:

  • (Fixnum)

    The size of the original message, excluding header as an Int32.

[ GitHub ]

  
# File 'lib/mongo/protocol/compressed.rb', line 138

field :uncompressed_size, Int32

Instance Method Details

#compress(buffer) (private)

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/protocol/compressed.rb', line 156

def compress(buffer)
  if @compressor_id == NOOP_BYTE
    buffer.to_s.force_encoding(BSON::BINARY)
  elsif @compressor_id == ZLIB_BYTE
    Zlib::Deflate.deflate(buffer.to_s, @zlib_compression_level).force_encoding(BSON::BINARY)
  elsif @compressor_id == SNAPPY_BYTE
    Snappy.deflate(buffer.to_s).force_encoding(BSON::BINARY)
  elsif @compressor_id == ZSTD_BYTE
    # DRIVERS-600 will allow this to be configurable in the future
    Zstd.compress(buffer.to_s).force_encoding(BSON::BINARY)
  end
end

#decompress(compressed_message) (private)

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/protocol/compressed.rb', line 169

def decompress(compressed_message)
  if @compressor_id == NOOP_BYTE
    BSON::ByteBuffer.new(compressed_message)
  elsif @compressor_id == ZLIB_BYTE
    BSON::ByteBuffer.new(Zlib::Inflate.inflate(compressed_message))
  elsif @compressor_id == SNAPPY_BYTE
    BSON::ByteBuffer.new(Snappy.inflate(compressed_message))
  elsif @compressor_id == ZSTD_BYTE
    BSON::ByteBuffer.new(Zstd.decompress(compressed_message))
  end
end

#maybe_inflateProtocol::Message

This method is for internal use only.

Inflates an OP_COMRESSED message and returns the original message.

Returns:

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/protocol/compressed.rb', line 95

def maybe_inflate
  message = Registry.get(@original_op_code).allocate
  buf = decompress(@compressed_message)

  message.send(:fields).each do |field|
    if field[:multi]
      Message.deserialize_array(message, buf, field)
    else
      Message.deserialize_field(message, buf, field)
    end
  end
  if message.is_a?(Msg)
    message.fix_after_deserialization
  end
  message
end

#serialize_fields(buffer, max_bson_size) (private)

Since:

  • 2.5.0

[ GitHub ]

  
# File 'lib/mongo/protocol/compressed.rb', line 148

def serialize_fields(buffer, max_bson_size)
  buf = BSON::ByteBuffer.new
  @original_message.send(:serialize_fields, buf, max_bson_size)
  @uncompressed_size = buf.length
  @compressed_message = compress(buf)
  super
end