/* 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); } } }