1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
|
//------------------------------------------------------------------------------
// <copyright file="Transactions.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------
/*
* Transactions support for ASP.NET pages
*
* Copyright (c) 2000, Microsoft Corporation
*/
namespace System.Web.Util {
using System.Collections;
using System.EnterpriseServices;
using System.Security.Permissions;
//
// Delegate to the transacted managed code
//
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public delegate void TransactedCallback();
//
// Delegate for the internal transacted execution
//
internal enum TransactedExecState {
CommitPending = 0,
AbortPending = 1,
Error = 2
}
internal delegate int TransactedExecCallback(); // return value 'int' for interop
//
// Utility class with to be called to do transactions
//
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public class Transactions {
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static void InvokeTransacted(TransactedCallback callback, TransactionOption mode) {
bool aborted = false;
InvokeTransacted(callback, mode, ref aborted);
}
/// <devdoc>
/// <para>[To be supplied.]</para>
/// </devdoc>
public static void InvokeTransacted(TransactedCallback callback, TransactionOption mode, ref bool transactionAborted) {
// check for hosting permission even if no user code on the stack
HttpRuntime.CheckAspNetHostingPermission(AspNetHostingPermissionLevel.Medium, SR.Transaction_not_supported_in_low_trust);
bool executeWithoutTransaction = false;
#if !FEATURE_PAL // FEATURE_PAL does not enable Transactions
if (Environment.OSVersion.Platform != PlatformID.Win32NT || Environment.OSVersion.Version.Major <= 4)
throw new PlatformNotSupportedException(SR.GetString(SR.RequiresNT));
#else // !FEATURE_PAL
throw new NotImplementedException("ROTORTODO");
#endif // !FEATURE_PAL
if (mode == TransactionOption.Disabled)
executeWithoutTransaction = true;
if (executeWithoutTransaction) {
// bypass the transaction logic
callback();
transactionAborted = false;
return;
}
TransactedInvocation call = new TransactedInvocation(callback);
TransactedExecCallback execCallback = new TransactedExecCallback(call.ExecuteTransactedCode);
PerfCounters.IncrementCounter(AppPerfCounter.TRANSACTIONS_PENDING);
int rc;
try {
rc = UnsafeNativeMethods.TransactManagedCallback(execCallback, (int)mode);
}
finally {
PerfCounters.DecrementCounter(AppPerfCounter.TRANSACTIONS_PENDING);
}
// rethrow the expection originally caught in managed code
if (call.Error != null)
throw new HttpException(null, call.Error);
PerfCounters.IncrementCounter(AppPerfCounter.TRANSACTIONS_TOTAL);
if (rc == 1) {
PerfCounters.IncrementCounter(AppPerfCounter.TRANSACTIONS_COMMITTED);
transactionAborted = false;
}
else if (rc == 0) {
PerfCounters.IncrementCounter(AppPerfCounter.TRANSACTIONS_ABORTED);
transactionAborted = true;
}
else {
throw new HttpException(SR.GetString(SR.Cannot_execute_transacted_code));
}
}
// Class with wrappers to ContextUtil that don't throw
internal class Utils {
private Utils() {
}
/*
internal static String TransactionId {
get {
String id = null;
try {
id = ContextUtil.TransactionId.ToString();
}
catch {
}
return id;
}
}
*/
internal static bool IsInTransaction {
get {
bool inTransaction = false;
try {
inTransaction = ContextUtil.IsInTransaction;
}
catch {
}
return inTransaction;
}
}
internal static bool AbortPending {
get {
bool aborted = false;
try {
if (ContextUtil.MyTransactionVote == TransactionVote.Abort)
aborted = true;
}
catch {
}
return aborted;
}
}
}
// Managed class encapsulating the transacted call
internal class TransactedInvocation {
private TransactedCallback _callback;
private Exception _error;
internal TransactedInvocation(TransactedCallback callback) {
_callback = callback;
}
internal int ExecuteTransactedCode() {
TransactedExecState state = TransactedExecState.CommitPending;
try {
_callback();
if (Transactions.Utils.AbortPending)
state = TransactedExecState.AbortPending;
}
catch (Exception e) {
_error = e; // remember exception to be rethrown back in managed code
state = TransactedExecState.Error;
}
return (int)state;
}
internal Exception Error {
get { return _error; }
}
}
}
}
|