Skip to content

Commit 1c5493f

Browse files
CSHARP-1991: Add zlib and snappy compressions.
1 parent d701854 commit 1c5493f

File tree

91 files changed

+2518
-2043
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+2518
-2043
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ Please see our [guidelines](CONTRIBUTING.md) for contributing to the driver.
103103
* Teun Duynstee [email protected]
104104
* Einar Egilsson https://github.com/einaregilsson
105105
* Ken Egozi [email protected]
106+
* Alexander Endris https://github.com/AlexEndris
106107
* Daniel Goldman [email protected]
107108
* Simon Green [email protected]
108109
* James Hadwen [email protected]

build.cake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ Task("BuildArtifacts")
9696
fileNames.Add("DnsClient.dll");
9797
}
9898

99+
// SharpCompress.dll is needed by Sandcastle
100+
if (targetFramework == "net452" && project == "MongoDB.Driver.Core")
101+
{
102+
fileNames.Add("SharpCompress.dll");
103+
}
104+
99105
foreach (var fileName in fileNames)
100106
{
101107
var fromFile = fromDirectory.CombineWithFilePath(fileName);

evergreen/evergreen.yml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,6 +434,18 @@ axes:
434434
variables:
435435
SSL: "nossl"
436436

437+
- id: compressor
438+
display_name: Compressor
439+
values:
440+
- id: "zlib"
441+
display_name: Zlib
442+
variables:
443+
COMPRESSOR: "zlib"
444+
- id: "snappy"
445+
display_name: Snappy
446+
variables:
447+
COMPRESSOR: "snappy"
448+
437449
buildvariants:
438450

439451
- name: windows-64-compile
@@ -457,6 +469,20 @@ buildvariants:
457469
tasks:
458470
- name: test
459471

472+
- matrix_name: "tests-zlib-compression"
473+
matrix_spec: { compressor : "zlib", auth: "noauth", ssl: "nossl", version: ["3.4", "3.6", "4.0", "latest"], topology: "standalone", os: "*" }
474+
display_name: "${version} ${compressor} ${topology} ${auth} ${ssl} ${os} "
475+
tags: ["tests-variant"]
476+
tasks:
477+
- name: "test"
478+
479+
#- matrix_name: "tests-snappy-compression"
480+
# matrix_spec: { compressor : "snappy", auth: "noauth", ssl: "nossl", version: ["3.4", "3.6", "4.0", "latest"], topology: "standalone", os: "*" }
481+
# display_name: "${version} ${compressor} ${topology} ${auth} ${ssl} ${os} "
482+
# tags: ["tests-variant"]
483+
# tasks:
484+
# - name: "test"
485+
460486
- name: atlas-connectivity-tests
461487
display_name: "Atlas Connectivity Tests"
462488
run_on:

src/MongoDB.Bson/IO/ByteBufferStream.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace MongoDB.Bson.IO
2323
/// Represents a Stream backed by an IByteBuffer. Similar to MemoryStream but backed by an IByteBuffer
2424
/// instead of a byte array and also implements the BsonStream interface for higher performance BSON I/O.
2525
/// </summary>
26-
public class ByteBufferStream : BsonStream
26+
public class ByteBufferStream : BsonStream, IStreamEfficientCopyTo
2727
{
2828
// private fields
2929
private IByteBuffer _buffer;
@@ -122,6 +122,19 @@ public override long Position
122122
}
123123

124124
// public methods
125+
/// <inheritdoc/>
126+
public void EfficientCopyTo(Stream destination)
127+
{
128+
long remainingCount;
129+
while ((remainingCount = Length - Position) > 0)
130+
{
131+
var segment = _buffer.AccessBackingBytes((int)Position);
132+
var count = (int)Math.Min(segment.Count, remainingCount);
133+
destination.Write(segment.Array, segment.Offset, count);
134+
Position += count;
135+
}
136+
}
137+
125138
/// <inheritdoc/>
126139
public override void Flush()
127140
{
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* Copyright 2019-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System.IO;
17+
18+
namespace MongoDB.Bson.IO
19+
{
20+
/// <summary>
21+
/// Represents the effective CopyTo method.
22+
/// </summary>
23+
public interface IStreamEfficientCopyTo
24+
{
25+
/// <summary>
26+
/// Copy the current stream to the destination without making unnecessary copies of the bytes.
27+
/// </summary>
28+
/// <param name="destination">The destination stream.</param>
29+
void EfficientCopyTo(Stream destination);
30+
}
31+
}

src/MongoDB.Bson/MongoDB.Bson.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
</PropertyGroup>
4343

4444
<ItemGroup>
45-
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.1" PrivateAssets="All" />
45+
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" Version="2.6.2" PrivateAssets="All" />
4646
</ItemGroup>
4747

4848
<ItemGroup Condition="'$(TargetFramework)'=='netstandard1.5'">
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/* Copyright 2019–present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System;
17+
using System.Collections.Concurrent;
18+
using System.Collections.Generic;
19+
using System.Linq;
20+
using MongoDB.Driver.Core.Configuration;
21+
using MongoDB.Driver.Core.Misc;
22+
23+
namespace MongoDB.Driver.Core.Compression
24+
{
25+
/// <summary>
26+
/// Represents a compressor source.
27+
/// </summary>
28+
public interface ICompressorSource
29+
{
30+
/// <summary>
31+
/// Gets or creates a compressor based on the compressor type.
32+
/// </summary>
33+
/// <param name="compressorType">The compressor type.</param>
34+
/// <returns>The compressor.</returns>
35+
ICompressor Get(CompressorType compressorType);
36+
}
37+
38+
internal class CompressorSource : ICompressorSource
39+
{
40+
#region static
41+
public static bool IsCompressorSupported(CompressorType compressorType)
42+
{
43+
switch (compressorType)
44+
{
45+
#if NET452 || NETSTANDARD2_0
46+
case CompressorType.Snappy:
47+
return true;
48+
#endif
49+
case CompressorType.Zlib:
50+
return true;
51+
case CompressorType.Noop: // This is realistically only used for testing
52+
return true;
53+
default:
54+
return false;
55+
}
56+
}
57+
#endregion
58+
59+
private readonly IReadOnlyList<CompressorConfiguration> _allowedCompressors;
60+
private readonly ConcurrentDictionary<CompressorType, ICompressor> _cache;
61+
62+
public CompressorSource(IReadOnlyList<CompressorConfiguration> allowedCompressors)
63+
{
64+
_allowedCompressors = Ensure.IsNotNull(allowedCompressors, nameof(allowedCompressors));
65+
_cache = new ConcurrentDictionary<CompressorType, ICompressor>();
66+
}
67+
68+
public ICompressor Get(CompressorType compressorType)
69+
{
70+
return _cache.GetOrAdd(compressorType, CreateCompressor);
71+
}
72+
73+
private ICompressor CreateCompressor(CompressorConfiguration compressorConfiguration)
74+
{
75+
switch (compressorConfiguration.Type)
76+
{
77+
case CompressorType.Noop:
78+
return new NoopCompressor();
79+
case CompressorType.Snappy:
80+
return new SnappyCompressor();
81+
case CompressorType.Zlib:
82+
{
83+
int? zlibCompressionLevel = null;
84+
if (compressorConfiguration.Properties.ContainsKey("Level"))
85+
{
86+
zlibCompressionLevel = (int)compressorConfiguration.Properties["Level"];
87+
}
88+
89+
return new ZlibCompressor(zlibCompressionLevel);
90+
}
91+
}
92+
93+
throw new NotSupportedException($"The compressor {compressorConfiguration.Type} is not supported.");
94+
}
95+
96+
private ICompressor CreateCompressor(CompressorType compressorType)
97+
{
98+
var compressorConfiguration = _allowedCompressors.FirstOrDefault(c => c.Type == compressorType);
99+
if (compressorConfiguration == null)
100+
{
101+
throw new NotSupportedException($"The compressor {compressorType} is not one of the allowed compressors.");
102+
}
103+
104+
return CreateCompressor(compressorConfiguration);
105+
}
106+
}
107+
}
Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright 2013-present MongoDB Inc.
1+
/* Copyright 2019–present MongoDB Inc.
22
*
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
@@ -13,34 +13,49 @@
1313
* limitations under the License.
1414
*/
1515

16+
using System.IO;
17+
1618
namespace MongoDB.Driver.Core.Compression
1719
{
18-
/// <summary>
19-
/// Represents a compressor.
20-
/// </summary>
21-
public interface ICompressor
22-
{
23-
/// <summary>
24-
/// Gets the name of the compressor.
25-
/// </summary>
26-
string Name { get; }
27-
28-
/// <summary>
29-
/// Gets the id of the compressor
30-
/// </summary>
31-
CompressorId Id { get; }
20+
/// <summary>
21+
/// Represents the compressor type.
22+
/// </summary>
23+
public enum CompressorType
24+
{
25+
// NOTE: the numeric values of the enum members MUST be kept in sync with the binary wire protocol
26+
27+
/// <summary>
28+
/// The content of the message is uncompressed. This is realistically only used for testing.
29+
/// </summary>
30+
Noop = 0,
31+
/// <summary>
32+
/// The content of the message is compressed using snappy.
33+
/// </summary>
34+
Snappy = 1,
35+
/// <summary>
36+
/// The content of the message is compressed using zlib.
37+
/// </summary>
38+
Zlib = 2
39+
}
40+
41+
/// <summary>
42+
/// Represents a compressor.
43+
/// </summary>
44+
public interface ICompressor
45+
{
46+
/// <summary>
47+
/// Gets the compressor type.
48+
/// </summary>
49+
CompressorType Type { get; }
3250

33-
/// <summary>
34-
/// Compresses the specified byte array with a given offset.
35-
/// </summary>
36-
/// <param name="bytesToCompress">Bytes to compress.</param>
37-
/// <param name="offset">Offset of the bytes.</param>
38-
byte[] Compress(byte[] bytesToCompress, int offset);
51+
/// <summary>
52+
/// Compresses the specified stream.
53+
/// </summary>
54+
void Compress(Stream input, Stream output);
3955

40-
/// <summary>
41-
/// Decompresses the specified byte array.
42-
/// </summary>
43-
/// <param name="bytesToDecompress">Bytes to decompress.</param>
44-
byte[] Decompress(byte[] bytesToDecompress);
45-
}
46-
}
56+
/// <summary>
57+
/// Decompresses the specified stream.
58+
/// </summary>
59+
void Decompress(Stream input, Stream output);
60+
}
61+
}

0 commit comments

Comments
 (0)