Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions src/MongoDB.Driver/GridFS/GridFSBucket.cs
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,11 @@ private GridFSUploadStream<TFileId> CreateUploadStream(IReadWriteBindingHandle b

private void EnsureIndexes(OperationContext operationContext, IReadWriteBindingHandle binding)
{
if (_options.AssumeIndexesExist)
{
return;
}

_ensureIndexesSemaphore.Wait(operationContext.RemainingTimeout, operationContext.CancellationToken);
try
{
Expand Down Expand Up @@ -926,6 +931,11 @@ private void EnsureIndexes(OperationContext operationContext, IReadWriteBindingH

private async Task EnsureIndexesAsync(OperationContext operationContext, IReadWriteBindingHandle binding)
{
if (_options.AssumeIndexesExist)
{
return;
}

await _ensureIndexesSemaphore.WaitAsync(operationContext.RemainingTimeout, operationContext.CancellationToken).ConfigureAwait(false);
try
{
Expand Down
34 changes: 34 additions & 0 deletions src/MongoDB.Driver/GridFS/GridFSBucketOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ namespace MongoDB.Driver.GridFS
public class GridFSBucketOptions
{
// fields
private bool _assumeIndexesExist;
private string _bucketName;
private int _chunkSizeBytes;
private ReadConcern _readConcern;
Expand All @@ -46,6 +47,7 @@ public GridFSBucketOptions()
public GridFSBucketOptions(GridFSBucketOptions other)
{
Ensure.IsNotNull(other, nameof(other));
_assumeIndexesExist = other.AssumeIndexesExist;
_bucketName = other.BucketName;
_chunkSizeBytes = other.ChunkSizeBytes;
_readConcern = other.ReadConcern;
Expand All @@ -60,6 +62,7 @@ public GridFSBucketOptions(GridFSBucketOptions other)
public GridFSBucketOptions(ImmutableGridFSBucketOptions other)
{
Ensure.IsNotNull(other, nameof(other));
_assumeIndexesExist = other.AssumeIndexesExist;
_bucketName = other.BucketName;
_chunkSizeBytes = other.ChunkSizeBytes;
_readConcern = other.ReadConcern;
Expand All @@ -68,6 +71,21 @@ public GridFSBucketOptions(ImmutableGridFSBucketOptions other)
}

// properties
/// <summary>
/// Gets or sets whether to assume the GridFS indexes already exist, skipping the index check and creation before the first upload.
/// </summary>
/// <remarks>
/// When <c>true</c>, the driver never verifies or creates the GridFS indexes, so the caller is responsible for ensuring they exist.
/// </remarks>
/// <value>
/// <c>true</c> if the GridFS indexes are assumed to exist; otherwise, <c>false</c>.
/// </value>
public bool AssumeIndexesExist
{
get { return _assumeIndexesExist; }
set { _assumeIndexesExist = value; }
}

/// <summary>
/// Gets or sets the bucket name.
/// </summary>
Expand Down Expand Up @@ -160,6 +178,7 @@ public static ImmutableGridFSBucketOptions Defaults
#endregion

// fields
private readonly bool _assumeIndexesExist;
private readonly string _bucketName;
private readonly int _chunkSizeBytes;
private readonly ReadConcern _readConcern;
Expand All @@ -183,6 +202,7 @@ public ImmutableGridFSBucketOptions()
public ImmutableGridFSBucketOptions(GridFSBucketOptions other)
{
Ensure.IsNotNull(other, nameof(other));
_assumeIndexesExist = other.AssumeIndexesExist;
_bucketName = other.BucketName;
_chunkSizeBytes = other.ChunkSizeBytes;
_readConcern = other.ReadConcern;
Expand All @@ -191,6 +211,20 @@ public ImmutableGridFSBucketOptions(GridFSBucketOptions other)
}

// properties
/// <summary>
/// Gets whether to assume the GridFS indexes already exist, skipping the index check and creation before the first upload.
/// </summary>
/// <remarks>
/// When <c>true</c>, the driver never verifies or creates the GridFS indexes, so the caller is responsible for ensuring they exist.
/// </remarks>
/// <value>
/// <c>true</c> if the GridFS indexes are assumed to exist; otherwise, <c>false</c>.
/// </value>
public bool AssumeIndexesExist
{
get { return _assumeIndexesExist; }
}

/// <summary>
/// Gets the bucket name.
/// </summary>
Expand Down
52 changes: 49 additions & 3 deletions tests/MongoDB.Driver.Tests/GridFS/GridFSBucketOptionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,32 @@ namespace MongoDB.Driver.Tests.GridFS
{
public class GridFSBucketOptionsTests
{
[Theory]
[ParameterAttributeData]
public void AssumeIndexesExist_get_should_return_expected_result(
[Values(false, true)]
bool value)
{
var subject = new GridFSBucketOptions { AssumeIndexesExist = value };

var result = subject.AssumeIndexesExist;

result.Should().Be(value);
}

[Theory]
[ParameterAttributeData]
public void AssumeIndexesExist_set_should_have_expected_result(
[Values(false, true)]
bool value)
{
var subject = new GridFSBucketOptions();

subject.AssumeIndexesExist = value;

subject.AssumeIndexesExist.Should().Be(value);
}

[Fact]
public void BucketName_get_should_return_expected_result()
{
Expand Down Expand Up @@ -103,11 +129,12 @@ public void ChunkSizeBytes_set_should_throw_when_value_is_invalid(
[Fact]
public void constructor_with_immutable_other_should_initialize_instance()
{
var mutable = new GridFSBucketOptions { BucketName = "bucket", ChunkSizeBytes = 123, ReadConcern = ReadConcern.Majority, ReadPreference = ReadPreference.Secondary, WriteConcern = WriteConcern.WMajority };
var mutable = new GridFSBucketOptions { AssumeIndexesExist = true, BucketName = "bucket", ChunkSizeBytes = 123, ReadConcern = ReadConcern.Majority, ReadPreference = ReadPreference.Secondary, WriteConcern = WriteConcern.WMajority };
var other = new ImmutableGridFSBucketOptions(mutable);

var result = new GridFSBucketOptions(other);

result.AssumeIndexesExist.Should().Be(other.AssumeIndexesExist);
result.BucketName.Should().Be(other.BucketName);
result.ChunkSizeBytes.Should().Be(other.ChunkSizeBytes);
result.ReadConcern.Should().Be(other.ReadConcern);
Expand All @@ -118,10 +145,11 @@ public void constructor_with_immutable_other_should_initialize_instance()
[Fact]
public void constructor_with_mutable_other_should_initialize_instance()
{
var other = new GridFSBucketOptions { BucketName = "bucket", ChunkSizeBytes = 123, ReadConcern = ReadConcern.Majority, ReadPreference = ReadPreference.Secondary, WriteConcern = WriteConcern.WMajority };
var other = new GridFSBucketOptions { AssumeIndexesExist = true, BucketName = "bucket", ChunkSizeBytes = 123, ReadConcern = ReadConcern.Majority, ReadPreference = ReadPreference.Secondary, WriteConcern = WriteConcern.WMajority };

var result = new GridFSBucketOptions(other);

result.AssumeIndexesExist.Should().Be(other.AssumeIndexesExist);
result.BucketName.Should().Be(other.BucketName);
result.ChunkSizeBytes.Should().Be(other.ChunkSizeBytes);
result.ReadConcern.Should().Be(other.ReadConcern);
Expand All @@ -134,6 +162,7 @@ public void constructor_with_no_arguments_should_initialize_instance_with_defaul
{
var result = new GridFSBucketOptions();

result.AssumeIndexesExist.Should().BeFalse();
result.BucketName.Should().Be("fs");
result.ChunkSizeBytes.Should().Be(255 * 1024);
result.ReadPreference.Should().BeNull();
Expand Down Expand Up @@ -203,6 +232,19 @@ public void WriteConcern_set_should_have_expected_result()

public class ImmutableGridFSBucketOptionsTests
{
[Theory]
[ParameterAttributeData]
public void AssumeIndexesExist_get_should_return_expected_result(
[Values(false, true)]
bool value)
{
var subject = new ImmutableGridFSBucketOptions(new GridFSBucketOptions { AssumeIndexesExist = value });

var result = subject.AssumeIndexesExist;

result.Should().Be(value);
}

[Fact]
public void BucketName_get_should_return_expected_result()
{
Expand All @@ -228,6 +270,7 @@ public void constructor_with_arguments_should_initialize_instance()
{
var mutable = new GridFSBucketOptions
{
AssumeIndexesExist = true,
BucketName = "bucket",
ChunkSizeBytes = 123,
ReadConcern = ReadConcern.Majority,
Expand All @@ -237,6 +280,7 @@ public void constructor_with_arguments_should_initialize_instance()

var result = new ImmutableGridFSBucketOptions(mutable);

result.AssumeIndexesExist.Should().BeTrue();
result.BucketName.Should().Be("bucket");
result.ChunkSizeBytes.Should().Be(123);
result.ReadConcern.Should().Be(ReadConcern.Majority);
Expand All @@ -247,8 +291,9 @@ public void constructor_with_arguments_should_initialize_instance()
[Fact]
public void constructor_with_no_arguments_should_initialize_instance_with_default_values()
{
var result = new GridFSBucketOptions();
var result = new ImmutableGridFSBucketOptions();

result.AssumeIndexesExist.Should().BeFalse();
result.BucketName.Should().Be("fs");
result.ChunkSizeBytes.Should().Be(255 * 1024);
result.ReadConcern.Should().BeNull();
Expand All @@ -270,6 +315,7 @@ public void Defaults_get_should_return_expected_result()
{
var result = ImmutableGridFSBucketOptions.Defaults;

result.AssumeIndexesExist.Should().BeFalse();
result.BucketName.Should().Be("fs");
result.ChunkSizeBytes.Should().Be(255 * 1024);
result.ReadConcern.Should().BeNull();
Expand Down
59 changes: 59 additions & 0 deletions tests/MongoDB.Driver.Tests/GridFS/GridFSBucketTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using MongoDB.Bson;
using MongoDB.Driver.Core.Clusters;
Expand Down Expand Up @@ -703,6 +704,52 @@ public void GridFS_should_work_with_strict_stable_api(
}
}

[Theory]
[ParameterAttributeData]
[Trait("Category", "Integration")]
public async Task Upload_should_create_indexes_unless_AssumeIndexesExist_is_true(
[Values(false, true)] bool assumeIndexesExist,
[Values(false, true)] bool async)
{
RequireServer.Check();
var client = DriverTestConfiguration.Client;
var database = client.GetDatabase(DriverTestConfiguration.DatabaseNamespace.DatabaseName);
var options = new GridFSBucketOptions { AssumeIndexesExist = assumeIndexesExist };
var subject = new GridFSBucket(database, options);
await DropBucketAsync(subject, async);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: I would say we can use async api for setup/clean up. There is no perks in executing sync code for setup.


try
{
if (async)
{
await subject.UploadFromBytesAsync("filename", new byte[] { 0 });
}
else
{
subject.UploadFromBytes("filename", new byte[] { 0 });
}

var filesIndexes = database.GetCollection<BsonDocument>("fs.files").Indexes.List().ToList();
var chunksIndexes = database.GetCollection<BsonDocument>("fs.chunks").Indexes.List().ToList();
if (assumeIndexesExist)
{
filesIndexes.Should().NotContain(index => index["name"] == "filename_1_uploadDate_1");
chunksIndexes.Should().NotContain(index => index["name"] == "files_id_1_n_1");
}
else
{
filesIndexes.Should().Contain(index => index["name"] == "filename_1_uploadDate_1");
chunksIndexes.Should().Contain(index => index["name"] == "files_id_1_n_1");
}
}
finally
{
// restore shared state: with AssumeIndexesExist the upload leaves fs.* non-empty and without the
// GridFS indexes, which would suppress index creation for later tests reusing the default bucket
await DropBucketAsync(subject, async);
}
}

// private methods
private GridFSBucket CreateSubject(GridFSBucketOptions options = null)
{
Expand All @@ -723,5 +770,17 @@ private void EnsureBucketExists(IGridFSBucket bucket)
{
bucket.UploadFromBytes("filename", new byte[0]);
}

private async Task DropBucketAsync(IGridFSBucket bucket, bool async)
{
if (async)
{
await bucket.DropAsync();
}
else
{
bucket.Drop();
}
}
}
}