internal void Begin() { try { if (_state == TransactionState.Active) { throw new InvalidOperationException("Transaction is already active"); } CheckThread(); if (_threadFlag != null) { throw new InvalidOperationException("Nested transactions are not allowed!"); } _threadFlag = true; _startTime = Clock.CurrentTimeMillis(); var request = TransactionCreateCodec.EncodeRequest(_options.GetTimeoutMillis(), _options.GetDurability(), (int)_options.GetTransactionType(), _threadId); var response = Invoke(request); _txnId = TransactionCreateCodec.DecodeResponse(response).Response; _state = TransactionState.Active; } catch (Exception e) { _threadFlag = null; throw ExceptionUtil.Rethrow(e); } }
/// <summary> /// Begins the transaction. /// </summary> public async Task BeginAsync() { if (State != TransactionState.None) { throw new InvalidOperationException("The transaction context is already involved in a transaction."); } var asyncContext = AsyncContext.Current; lock (_inTransactionMutex) { // this is used to prevent an asynchronous context from being in multiple (thus nested) transactions, // it was implemented, before async, via a [ThreadStatic] boolean (when everything was bound to // threads) which cannot be appropriate anymore. instead we move it to the async context. if (asyncContext.InTransaction) { throw new InvalidOperationException("Nested transactions are not supported."); } asyncContext.InTransaction = true; } _connection = _cluster.Members.GetRandomConnection(); if (_connection == null) { throw _cluster.State.ThrowClientOfflineException(); } _threadId = ContextId; //_startTime = Clock.Milliseconds; HConsole.WriteLine(this, $"Begin transaction on context #{ContextId}"); try { // codec wants 0 for server config, -1 for infinite (?) var timeoutMs = _options.Timeout.RoundedMilliseconds(false); var requestMessage = TransactionCreateCodec.EncodeRequest(timeoutMs, _options.Durability, (int)_options.Type, ContextId); var responseMessage = await _cluster.Messaging.SendToMemberAsync(requestMessage, _connection).CfAwait(); TransactionId = TransactionCreateCodec.DecodeResponse(responseMessage).Response; State = TransactionState.Active; } catch { lock (_inTransactionMutex) asyncContext.InTransaction = false; _threadId = 0; //_startTime = 0; TransactionId = default; State = TransactionState.None; throw; } }