Skip to content

Commit

Permalink
Revamped TransactionConfiguration, DI enable TX class instantiation. (d…
Browse files Browse the repository at this point in the history
…otnet#37)

* Revamped transaction configuration to use type names.
Silo setup using new config to register classes in DI.
Silo defaults to InCluster type for Transactions with MemoryStorageLog.
Fix TrasactionLog filename type.

* Address feedback.

* Address feedback: revert Silo whitespace changes, modify tx config ToString output.

* Removed unneeded TypeName configuration values.

* Apply null coalescing in config log.
  • Loading branch information
Attila Hajdrik authored and jason-bragg committed Apr 14, 2017
1 parent 9ef2956 commit 83e611b
Show file tree
Hide file tree
Showing 17 changed files with 185 additions and 181 deletions.
9 changes: 0 additions & 9 deletions src/Orleans/Configuration/AzureTransactionLogOptions.cs

This file was deleted.

27 changes: 26 additions & 1 deletion src/Orleans/Configuration/ClientConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using System.Threading;
using System.Xml;
using Orleans.Providers;
using Orleans.Transactions;

namespace Orleans.Runtime.Configuration
{
Expand Down Expand Up @@ -66,6 +67,8 @@ public enum GatewayProviderType
/// </summary>
public GatewayProviderType GatewayProvider { get; set; }

public TransactionsConfiguration Transactions { get; private set; }

/// <summary>
/// Specifies a unique identifier of this deployment.
/// If the silos are deployed on Azure (run as workers roles), deployment id is set automatically by Azure runtime,
Expand Down Expand Up @@ -221,6 +224,7 @@ public ClientConfiguration()
StatisticsCollectionLevel = NodeConfiguration.DEFAULT_STATS_COLLECTION_LEVEL;
LimitManager = new LimitManager();
ProviderConfigurations = new Dictionary<string, ProviderCategoryConfiguration>();
Transactions = new TransactionsConfiguration();
}

public void Load(TextReader input)
Expand Down Expand Up @@ -331,6 +335,9 @@ internal void LoadFromXml(XmlElement root)
case "Telemetry":
ConfigUtilities.ParseTelemetry(child);
break;
case "Transactions":
Transactions.Load(child);
break;
default:
if (child.LocalName.EndsWith("Providers", StringComparison.Ordinal))
{
Expand Down Expand Up @@ -366,7 +373,6 @@ public static ClientConfiguration LoadFromFile(string fileName)
config.SourceFile = fileName;
return config;
}

}

/// <summary>
Expand Down Expand Up @@ -511,6 +517,25 @@ public override string ToString()
sb.Append(ConfigUtilities.IStatisticsConfigurationToString(this));
sb.Append(LimitManager);
sb.AppendFormat(base.ToString());

sb.AppendLine("Transactions");
sb.AppendLine($" LogStorageTypeName: {Transactions.LogStorageType?.AssemblyQualifiedName ?? "N/A"}");
sb.AppendLine($" TransactionManagerTypeName: {Transactions.TransactionManagerType?.AssemblyQualifiedName ?? "N/A"}");
sb.AppendLine($" TransactionServiceFactoryTypeName: {Transactions.TransactionServiceFactoryType?.AssemblyQualifiedName ?? "N/A"}");
sb.AppendLine($" TransactionIdAllocationBatchSize: {Transactions.TransactionIdAllocationBatchSize}");
sb.AppendLine($" AvailableTransactionIdThreshold: {Transactions.AvailableTransactionIdThreshold}");
sb.AppendLine($" TransactionManagerProxyCount: {Transactions.TransactionManagerProxyCount}");
sb.AppendLine($" TransactionRecordPreservationDuration: {Transactions.TransactionRecordPreservationDuration}");
if (!string.IsNullOrWhiteSpace(Transactions.LogConnectionString))
{
sb.AppendLine($" LogConnectionString: {ConfigUtilities.RedactConnectionStringInfo(Transactions.LogConnectionString)}");
}
if (!string.IsNullOrWhiteSpace(Transactions.LogTableName))
{
sb.AppendLine($" LogTableName: {Transactions.LogTableName}");
}
sb.AppendLine($" TransactionManagerProxyCount: {Transactions.TransactionManagerProxyCount}");

#if !NETSTANDARD
sb.Append(" .NET: ").AppendLine();
int workerThreads;
Expand Down
18 changes: 18 additions & 0 deletions src/Orleans/Configuration/GlobalConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,24 @@ public override string ToString()
sb.AppendFormat(" Providers:").AppendLine();
sb.Append(ProviderConfigurationUtility.PrintProviderConfigurations(ProviderConfigurations));

sb.AppendLine(" Transactions");
sb.AppendLine($" LogStorageTypeName: {Transactions.LogStorageType?.AssemblyQualifiedName ?? "N/A"}");
sb.AppendLine($" TransactionManagerTypeName: {Transactions.TransactionManagerType?.AssemblyQualifiedName ?? "N/A"}");
sb.AppendLine($" TransactionServiceFactoryTypeName: {Transactions.TransactionServiceFactoryType?.AssemblyQualifiedName ?? "N/A"}");
sb.AppendLine($" TransactionIdAllocationBatchSize: {Transactions.TransactionIdAllocationBatchSize}");
sb.AppendLine($" AvailableTransactionIdThreshold: {Transactions.AvailableTransactionIdThreshold}");
sb.AppendLine($" TransactionManagerProxyCount: {Transactions.TransactionManagerProxyCount}");
sb.AppendLine($" TransactionRecordPreservationDuration: {Transactions.TransactionRecordPreservationDuration}");
if (!string.IsNullOrWhiteSpace(Transactions.LogConnectionString))
{
sb.AppendLine($" LogConnectionString: {ConfigUtilities.RedactConnectionStringInfo(Transactions.LogConnectionString)}");
}
if (!string.IsNullOrWhiteSpace(Transactions.LogTableName))
{
sb.AppendLine($" LogTableName: {Transactions.LogTableName}");
}
sb.AppendLine($" TransactionManagerProxyCount: {Transactions.TransactionManagerProxyCount}");

return sb.ToString();
}

Expand Down
130 changes: 51 additions & 79 deletions src/Orleans/Configuration/TransactionsConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
using Orleans.Runtime.Configuration;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace Orleans.Transactions
Expand All @@ -13,50 +8,21 @@ namespace Orleans.Transactions
public class TransactionsConfiguration
{
/// <summary>
/// Log configuration that controls the persistent storage used for the transaction log.
/// The LogStorageType value controls the persistent storage used for the transaction log. This value is resolved from the LogStorageTypeName attribute if XML configuration is used.
/// </summary>
public enum TransactionLogType
{
/// <summary>Store transaction log in memory.
/// This option is should only be used for testing because the log has to be durable.</summary>
Memory,
/// <summary>AzureTable is used to store transaction log.
/// This option should be used in production.</summary>
AzureTable
}

/// <summary>
/// Orleans framework supported transaction manager types
/// </summary>
public enum OrleansTransactionManagerType
{
/// <summary>
/// Transaction manager hosted in a grain. Viable for test, development, and services with low transactional performance requirements
/// If not specificed Transaction Manager type will default to GrainBased
/// </summary>
GrainBased,
/// <summary>
/// Transaction manager hosted in an Orleans client service.
/// </summary>
ClientService,
}

public static readonly string DefaultOrleansTransactionManagerType = OrleansTransactionManagerType.GrainBased.ToString();
public Type LogStorageType { get; set; }

/// <summary>
/// The LogType attribute controls the persistent storage used for the transaction log.
/// The TransactionManager value controls the type of the TransactionManager will be used. This value is resolved from the TransactionManagerTypeName attribute if XML configuration is used.
/// This value must be in pair with TransactionServiceFactoryType attribute.
/// </summary>
public TransactionLogType LogType { get; set; }
public Type TransactionManagerType { get; set; }

/// <summary>
/// Whether to clear the log on Transaction Service startup. Used primarily for testing purposes
/// The TransactionServiceFactoryType value controls the type of the TransactionServiceFactoryTypeName will be used. This value is resolved from the TransactionServiceFactoryTypeName attribute if XML configuration is used.
/// This value must be in pair with TransactionManagerType attribute.
/// </summary>
public bool ClearLogOnStartup { get; set; }

/// <summary>
/// Provides configuration options for an external transaction log provider.
/// </summary>
public AzureTableTransactionLogOptions TableBasedLogOptions { get; set; }
public Type TransactionServiceFactoryType { get; set; }

/// <summary>
/// The number of new Transaction Ids allocated on every write to the log.
Expand All @@ -82,15 +48,21 @@ public enum OrleansTransactionManagerType
/// </summary>
public TimeSpan TransactionRecordPreservationDuration { get; set; }

public string TransactionManagerType { get; set; } = DefaultOrleansTransactionManagerType;
/// <summary>
/// Provides connection string for an external table based transaction log storage.
/// </summary>
public string LogConnectionString { get; set; }

/// <summary>
/// Provides name of the table for an external table based transaction log storage.
/// </summary>
public string LogTableName { get; set; }

/// <summary>
/// TransactionsConfiguration constructor.
/// </summary>
public TransactionsConfiguration()
{
LogType = TransactionLogType.Memory;
ClearLogOnStartup = false;
TransactionManagerProxyCount = 1;
TransactionIdAllocationBatchSize = 50000;
AvailableTransactionIdThreshold = 20000;
Expand All @@ -103,33 +75,40 @@ public TransactionsConfiguration()
/// <param name="child"></param>
public void Load(XmlElement child)
{
if (child.HasAttribute("LogType"))
if (child.HasAttribute("LogStorageTypeName"))
{
var logStorageTypeName = child.GetAttribute("LogStorageTypeName");
this.LogStorageType = ResolveType(logStorageTypeName, nameof(logStorageTypeName));
}

if (child.HasAttribute("TransactionManagerTypeName"))
{
this.LogType = GetLogType(child.GetAttribute("LogType"));
var transactionManagerTypeName = child.GetAttribute("TransactionManagerTypeName");
this.TransactionManagerType = ResolveType(transactionManagerTypeName, nameof(transactionManagerTypeName));
}

if (child.HasAttribute("ClearLogOnStartup"))
if (child.HasAttribute("TransactionServiceFactoryTypeName"))
{
this.ClearLogOnStartup = ConfigUtilities.ParseBool(child.GetAttribute("ClearLogOnStartup"),
"Invalid boolean value for the ClearLogOnStartup element");
var transactionServiceFactoryTypeName = child.GetAttribute("TransactionServiceFactoryTypeName");
this.TransactionServiceFactoryType = ResolveType(transactionServiceFactoryTypeName, nameof(transactionServiceFactoryTypeName));
}

if (child.HasAttribute("TransactionIdAllocationBatchSize"))
{
this.TransactionIdAllocationBatchSize = ConfigUtilities.ParseInt(child.GetAttribute("TransactionIdAllocationBatchSize"),
"Invalid boolean value for the TransactionIdAllocationBatchSize element");
"Invalid integer value for the TransactionIdAllocationBatchSize element");
}

if (child.HasAttribute("AvailableTransactionIdThreshold"))
{
this.AvailableTransactionIdThreshold = ConfigUtilities.ParseInt(child.GetAttribute("AvailableTransactionIdThreshold"),
"Invalid boolean value for the AvailableTransactionIdThreshold element");
"Invalid integer value for the AvailableTransactionIdThreshold element");
}

if (child.HasAttribute("TransactionManagerProxyCount"))
{
this.TransactionManagerProxyCount = ConfigUtilities.ParseInt(child.GetAttribute("TransactionManagerProxyCount"),
"Invalid boolean value for the TransactionManagerProxyCount element");
"Invalid integer value for the TransactionManagerProxyCount element");
}

if (child.HasAttribute("TransactionRecordPreservationDuration"))
Expand All @@ -138,45 +117,38 @@ public void Load(XmlElement child)
"Invalid TimeSpan value for the TransactionRecordPreservationDuration element");
}

var logConnectionString = default(string);
var logTableName = default(string);

if (child.HasAttribute("DataConnectionString"))
if (child.HasAttribute("LogConnectionString"))
{
logConnectionString = child.GetAttribute("DataConnectionString");
this.LogConnectionString = child.GetAttribute("LogConnectionString");
}

if (child.HasAttribute("LogTableName"))
{
logTableName = child.GetAttribute("LogTableName");
this.LogTableName = child.GetAttribute("LogTableName");
}

TableBasedLogOptions = new AzureTableTransactionLogOptions
{
ConnectionString = logConnectionString,
TableName = logTableName
};

if (child.HasAttribute("TransactionManagerType"))
{
this.TransactionManagerType = child.GetAttribute("TransactionManagerType");
}
}

private TransactionLogType GetLogType(string type)
private static Type ResolveType(string typeName, string configurationValueName)
{
if (type.Equals("Memory", StringComparison.InvariantCultureIgnoreCase))
{
return TransactionLogType.Memory;
}
Type resolvedType = null;

if (type.Equals("AzureTable", StringComparison.InvariantCultureIgnoreCase))
if (!string.IsNullOrWhiteSpace(typeName))
{
return TransactionLogType.AzureTable;
resolvedType = Type.GetType(typeName);

if (resolvedType == null)
{
throw new InvalidOperationException($"Cannot locate the type specified in the configuration file for {configurationValueName}: '{typeName}'.");
}

if (!resolvedType.IsClass || resolvedType.IsAbstract)
{
throw new InvalidOperationException($"{resolvedType} is either not a class or an abstract class.");
}
}

throw new FormatException(string.Format("Invalid value {0} for TransactionLogType", type));
return resolvedType;
}

}
}
3 changes: 1 addition & 2 deletions src/Orleans/Orleans.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@
<Compile Include="Async\TaskExtensions.cs" />
<Compile Include="CodeGeneration\GeneratedAssembly.cs" />
<Compile Include="CodeGeneration\GenericMethodInvoker.cs" />
<Compile Include="Configuration\AzureTransactionLogOptions.cs" />
<Compile Include="Configuration\GrainServiceConfiguration.cs" />
<Compile Include="Core\ClientBuilder.cs" />
<Compile Include="Core\ClientBuilderExtensions.cs" />
Expand Down Expand Up @@ -202,7 +201,7 @@
<Compile Include="Transactions\TransactionalStateConfiguration.cs" />
<Compile Include="Transactions\TransactionManager.cs" />
<Compile Include="Transactions\TransactionManagerService.cs" />
<Compile Include="Transactions\TrasactionLog.cs" />
<Compile Include="Transactions\TransactionLog.cs" />
<Compile Include="Streams\Providers\StreamProviderUtils.cs" />
<Compile Include="Streams\PubSub\StreamSubscriptionManagerExtensions.cs" />
<Compile Include="Utils\Factory.cs" />
Expand Down
File renamed without changes.
15 changes: 7 additions & 8 deletions src/Orleans/Transactions/TransactionManager.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

using System;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
Expand Down Expand Up @@ -59,7 +58,7 @@ protected TransactionManagerBase(TransactionLog transactionLog, TransactionsConf
checkpointedLSN = 0;

gcTimer = new Timer(GC);

this.Logger = LogManager.GetLogger("TransactionManager");
}

Expand Down Expand Up @@ -231,9 +230,9 @@ public void CommitTransaction(TransactionInfo transactionInfo)
}
else
{
// Don't have a record of the transaction any more so presumably it's aborted.
throw new OrleansTransactionAbortedException(transactionInfo.TransactionId, "Transaction presumed to be aborted");
}
// Don't have a record of the transaction any more so presumably it's aborted.
throw new OrleansTransactionAbortedException(transactionInfo.TransactionId, "Transaction presumed to be aborted");
}
}

public TransactionStatus GetTransactionStatus(long transactionId, out OrleansTransactionAbortedException abortingException)
Expand Down Expand Up @@ -267,7 +266,7 @@ public long GetReadOnlyTransactionId()
long readId = activeTransactionsTracker.GetSmallestActiveTransactionId();
if (readId > 0)
{
readId--;
readId--;
}
return readId;
}
Expand Down Expand Up @@ -510,7 +509,7 @@ private void GC(object args)
transactionsTable.TryRemove(txRecord.Key, out temp);
}
}
}
}
}

//
Expand Down
Loading

0 comments on commit 83e611b

Please sign in to comment.