Skip to content

Commit 1f91e97

Browse files
committed
CSHARP-2672: Fix snappy compression
1 parent 517a7ee commit 1f91e97

File tree

6 files changed

+59
-24
lines changed

6 files changed

+59
-24
lines changed

Release Notes/Release Notes v2.9.2.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
# .NET Driver Version 2.9.2 Placeholder Release Notes
1+
# .NET Driver Version 2.9.2 Release Notes
22

3-
The main new features in 2.9.2 are:
3+
This is a patch release that fixes several bugs reported since 2.9.1 was released.
44

5+
Most notably in the .NET Framework version of the driver, snappy compression now works properly with servers ≥ 3.6.
56

67
An online version of these release notes is available at:
78

@@ -18,3 +19,4 @@ http://mongodb.github.io/mongo-csharp-driver/
1819

1920
## Upgrading
2021

22+
There are no known backwards breaking changes in this release.

evergreen/evergreen.yml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ functions:
218218
export FLE_AWS_ACCESS_KEY_ID=${FLE_AWS_ACCESS_KEY_ID}
219219
export FLE_AWS_SECRET_ACCESS_KEY=${FLE_AWS_SECRET_ACCESS_KEY}
220220
${PREPARE_SHELL}
221-
AUTH=${AUTH} SSL=${SSL} MONGODB_URI="${MONGODB_URI}" TOPOLOGY=${TOPOLOGY} OS=${OS} evergreen/run-tests.sh
221+
AUTH=${AUTH} SSL=${SSL} MONGODB_URI="${MONGODB_URI}" TOPOLOGY=${TOPOLOGY} OS=${OS} COMPRESSOR=${COMPRESSOR} evergreen/run-tests.sh
222222
223223
run-atlas-connectivity-tests:
224224
- command: shell.exec
@@ -477,18 +477,18 @@ buildvariants:
477477
- name: test
478478

479479
- matrix_name: "tests-zlib-compression"
480-
matrix_spec: { compressor : "zlib", auth: "noauth", ssl: "nossl", version: ["3.4", "3.6", "4.0", "4.2", "latest"], topology: "standalone", os: "*" }
480+
matrix_spec: { compressor : "zlib", auth: "noauth", ssl: "nossl", version: ["3.6", "4.0", "4.2", "latest"], topology: "standalone", os: "*" }
481481
display_name: "${version} ${compressor} ${topology} ${auth} ${ssl} ${os} "
482482
tags: ["tests-variant"]
483483
tasks:
484484
- name: "test"
485485

486-
#- matrix_name: "tests-snappy-compression"
487-
# matrix_spec: { compressor : "snappy", auth: "noauth", ssl: "nossl", version: ["3.4", "3.6", "4.0", "4.2", "latest"], topology: "standalone", os: "*" }
488-
# display_name: "${version} ${compressor} ${topology} ${auth} ${ssl} ${os} "
489-
# tags: ["tests-variant"]
490-
# tasks:
491-
# - name: "test"
486+
- matrix_name: "tests-snappy-compression"
487+
matrix_spec: { compressor : "snappy", auth: "noauth", ssl: "nossl", version: ["3.6", "4.0", "4.2", "latest"], topology: "standalone", os: "*" }
488+
display_name: "${version} ${compressor} ${topology} ${auth} ${ssl} ${os} "
489+
tags: ["tests-variant"]
490+
tasks:
491+
- name: "test"
492492

493493
- name: atlas-connectivity-tests
494494
display_name: "Atlas Connectivity Tests"

evergreen/run-tests.sh

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#!/bin/bash
1+
#!/usr/bin/env bash
22

33
set -o xtrace # Write all commands first to stderr
44
set -o errexit # Exit the script with error if any of the commands fail
@@ -14,6 +14,7 @@ AUTH=${AUTH:-noauth}
1414
SSL=${SSL:-nossl}
1515
MONGODB_URI=${MONGODB_URI:-}
1616
TOPOLOGY=${TOPOLOGY:-server}
17+
COMPRESSOR=${COMPRESSOR:-none}
1718

1819
############################################
1920
# Functions #
@@ -30,6 +31,15 @@ provision_ssl () {
3031
fi
3132
}
3233

34+
provision_compressor () {
35+
uri_environment_variable_name=$1
36+
if [[ "${!uri_environment_variable_name}" =~ "/?" ]]; then
37+
export $uri_environment_variable_name="${!uri_environment_variable_name}&compressors=$COMPRESSOR"
38+
else
39+
export $uri_environment_variable_name="${!uri_environment_variable_name}/?compressors=$COMPRESSOR"
40+
fi
41+
}
42+
3343
############################################
3444
# Main Program #
3545
############################################
@@ -51,7 +61,14 @@ if [ "$SSL" != "nossl" ]; then
5161
fi
5262
fi
5363

54-
echo "Running $AUTH tests over $SSL for $TOPOLOGY and connecting to $MONGODB_URI"
64+
if [ "$COMPRESSOR" != "none" ]; then
65+
provision_compressor MONGODB_URI
66+
if [ "$TOPOLOGY" == "sharded_cluster" ]; then
67+
provision_compressor MONGODB_URI_WITH_MULTIPLE_MONGOSES
68+
fi
69+
fi
70+
71+
echo "Running $AUTH tests over $SSL for $TOPOLOGY with $COMPRESSOR compressor and connecting to $MONGODB_URI"
5572

5673
if [ "$OS" == "windows-64" ]; then
5774
export TARGET="Test"

src/MongoDB.Driver.Core/Core/Compression/SnappyCompressor.cs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@
1515

1616
using System;
1717
using System.IO;
18+
using System.Threading;
1819
using MongoDB.Driver.Core.Misc;
1920
#if NET452 || NETSTANDARD2_0
20-
using System.IO.Compression;
2121
using Snappy;
2222
#endif
2323

@@ -27,25 +27,40 @@ internal class SnappyCompressor : ICompressor
2727
{
2828
public CompressorType Type => CompressorType.Snappy;
2929

30+
/// <summary>
31+
/// Compresses the remainder of <paramref name="input"/>, writing the compressed data to
32+
/// <paramref name="output"/>.
33+
/// </summary>
34+
/// <param name="input"> The input stream.</param>
35+
/// <param name="output">The output stream.</param>
3036
public void Compress(Stream input, Stream output)
3137
{
3238
#if NET452 || NETSTANDARD2_0
33-
using (var snappyStream = new SnappyStream(output, CompressionMode.Compress, true))
34-
{
35-
input.EfficientCopyTo(snappyStream);
36-
}
39+
var uncompressedSize = (int) (input.Length - input.Position);
40+
var uncompressedBytes = new byte[uncompressedSize]; // does not include uncompressed message headers
41+
input.ReadBytes(uncompressedBytes, offset: 0, count: uncompressedSize, CancellationToken.None);
42+
var maxCompressedSize = SnappyCodec.GetMaxCompressedLength(uncompressedSize);
43+
var compressedBytes = new byte[maxCompressedSize];
44+
var compressedSize = SnappyCodec.Compress(uncompressedBytes, 0, uncompressedSize, compressedBytes, 0);
45+
output.Write(compressedBytes, 0, compressedSize);
3746
#else
3847
throw new NotSupportedException();
3948
#endif
4049
}
4150

51+
/// <summary>
52+
/// Decompresses the remainder of <paramref name="input"/>, writing the uncompressed data to <paramref name="output"/>.
53+
/// </summary>
54+
/// <param name="input">The input stream.</param>
55+
/// <param name="output">The output stream.</param>
4256
public void Decompress(Stream input, Stream output)
4357
{
4458
#if NET452 || NETSTANDARD2_0
45-
using (var snappyStream = new SnappyStream(input, CompressionMode.Decompress, true))
46-
{
47-
snappyStream.CopyTo(output);
48-
}
59+
var compressedSize = (int) (input.Length - input.Position);
60+
var compressedBytes = new byte[compressedSize];
61+
input.ReadBytes(compressedBytes, offset: 0, count: compressedSize, CancellationToken.None);
62+
var decompressedBytes = SnappyCodec.Uncompress(compressedBytes);
63+
output.Write(decompressedBytes, offset: 0, count: decompressedBytes.Length);
4964
#else
5065
throw new NotSupportedException();
5166
#endif

src/MongoDB.Driver.Core/Core/WireProtocol/Messages/CommandMessage.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,9 @@ public override bool MayBeCompressed
8181
{
8282
get
8383
{
84-
var section = _sections.OfType<Type0CommandMessageSection<BsonDocument>>().First();
85-
var commandName = section.Document.First().Name;
84+
var type0Section = _sections.OfType<Type0CommandMessageSection>().Single();
85+
var command = (BsonDocument)type0Section.Document; // could be a RawBsonDocument but that's OK
86+
var commandName = command.GetElement(0).Name;
8687

8788
if (__messagesNotToBeCompressed.Contains(commandName))
8889
{

src/MongoDB.Driver.Core/Core/WireProtocol/Messages/Encoders/BinaryEncoders/CompressedMessageBinaryEncoder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ public void WriteMessage(CompressedMessage message)
116116
stream.WriteInt32(responseTo);
117117
stream.WriteInt32((int)Opcode.Compressed);
118118
stream.WriteInt32((int)originalOpcode);
119-
stream.WriteInt32(uncompressedMessageLength - MessageHeaderLength);
119+
stream.WriteInt32(uncompressedMessageLength - MessageHeaderLength); // uncompressedSize
120120
stream.WriteByte((byte)compressorType);
121121
compressor.Compress(uncompressedMessageStream, stream);
122122
stream.BackpatchSize(messageStartPosition);

0 commit comments

Comments
 (0)