/* Copyright 2017-present MongoDB Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
using System.Threading;
using System.Threading.Tasks;
using MongoDB.Bson;
using MongoDB.Driver.Core.Bindings;
using MongoDB.Driver.Core.Misc;
namespace MongoDB.Driver
{
///
/// A client session handle.
///
///
internal sealed class ClientSessionHandle : IClientSessionHandle
{
// private fields
private readonly IMongoClient _client;
private readonly IClock _clock;
private readonly ICoreSessionHandle _coreSession;
private bool _disposed;
private readonly ClientSessionOptions _options;
private IServerSession _serverSession;
// constructors
///
/// Initializes a new instance of the class.
///
/// The client.
/// The options.
/// The wrapped session.
public ClientSessionHandle(IMongoClient client, ClientSessionOptions options, ICoreSessionHandle coreSession)
: this(client, options, coreSession, SystemClock.Instance)
{
}
internal ClientSessionHandle(IMongoClient client, ClientSessionOptions options, ICoreSessionHandle coreSession, IClock clock)
{
_client = client;
_options = options;
_coreSession = coreSession;
_clock = clock;
}
// public properties
///
public IMongoClient Client => _client;
///
public BsonDocument ClusterTime => _coreSession.ClusterTime;
///
public bool IsImplicit => _coreSession.IsImplicit;
///
public bool IsInTransaction => _coreSession.IsInTransaction;
///
public BsonTimestamp OperationTime => _coreSession.OperationTime;
///
public ClientSessionOptions Options => _options;
///
public IServerSession ServerSession
{
get
{
if (_serverSession == null)
{
_serverSession = new ServerSession(_coreSession.ServerSession);
}
return _serverSession;
}
}
///
public ICoreSessionHandle WrappedCoreSession => _coreSession;
// public methods
///
public void AbortTransaction(CancellationToken cancellationToken = default(CancellationToken))
{
_coreSession.AbortTransaction(cancellationToken);
}
///
public Task AbortTransactionAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return _coreSession.AbortTransactionAsync(cancellationToken);
}
///
public void AdvanceClusterTime(BsonDocument newClusterTime)
{
_coreSession.AdvanceClusterTime(newClusterTime);
}
///
public void AdvanceOperationTime(BsonTimestamp newOperationTime)
{
_coreSession.AdvanceOperationTime(newOperationTime);
}
///
public void CommitTransaction(CancellationToken cancellationToken = default(CancellationToken))
{
_coreSession.CommitTransaction(cancellationToken);
}
///
public Task CommitTransactionAsync(CancellationToken cancellationToken = default(CancellationToken))
{
return _coreSession.CommitTransactionAsync(cancellationToken);
}
///
public void Dispose()
{
if (!_disposed)
{
_coreSession.Dispose();
_serverSession?.Dispose();
_disposed = true;
}
}
///
public IClientSessionHandle Fork()
{
return new ClientSessionHandle(_client, _options, _coreSession.Fork());
}
///
public void StartTransaction(TransactionOptions transactionOptions = null)
{
var effectiveTransactionOptions = GetEffectiveTransactionOptions(transactionOptions);
_coreSession.StartTransaction(effectiveTransactionOptions);
}
///
public TResult WithTransaction(Func callback, TransactionOptions transactionOptions = null, CancellationToken cancellationToken = default(CancellationToken))
{
Ensure.IsNotNull(callback, nameof(callback));
return TransactionExecutor.ExecuteWithRetries(this, callback, transactionOptions, _clock, cancellationToken);
}
///
public Task WithTransactionAsync(Func> callbackAsync, TransactionOptions transactionOptions = null, CancellationToken cancellationToken = default(CancellationToken))
{
Ensure.IsNotNull(callbackAsync, nameof(callbackAsync));
return TransactionExecutor.ExecuteWithRetriesAsync(this, callbackAsync, transactionOptions, _clock, cancellationToken);
}
private TransactionOptions GetEffectiveTransactionOptions(TransactionOptions transactionOptions)
{
var defaultTransactionOptions = _options?.DefaultTransactionOptions;
var readConcern = transactionOptions?.ReadConcern ?? defaultTransactionOptions?.ReadConcern ?? _client.Settings?.ReadConcern ?? ReadConcern.Default;
var readPreference = transactionOptions?.ReadPreference ?? defaultTransactionOptions?.ReadPreference ?? _client.Settings?.ReadPreference ?? ReadPreference.Primary;
var writeConcern = transactionOptions?.WriteConcern ?? defaultTransactionOptions?.WriteConcern ?? _client.Settings?.WriteConcern ?? new WriteConcern();
var maxCommitTime = transactionOptions?.MaxCommitTime ?? defaultTransactionOptions?.MaxCommitTime;
return new TransactionOptions(readConcern, readPreference, writeConcern, maxCommitTime);
}
}
}