Created
February 26, 2015 20:52
-
-
Save ReubenBond/648584a770b615afaf04 to your computer and use it in GitHub Desktop.
Orleans: modifying internal provider config
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace Orleans.Azure.Silos | |
{ | |
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics; | |
using System.Linq; | |
using System.Net; | |
using System.Reflection; | |
using Microsoft.WindowsAzure; | |
using Microsoft.WindowsAzure.Diagnostics; | |
using Microsoft.WindowsAzure.ServiceRuntime; | |
using Orleans.Runtime.Configuration; | |
using Orleans.Runtime.Host; | |
/// <summary> | |
/// The worker role. | |
/// </summary> | |
public class WorkerRole : RoleEntryPoint | |
{ | |
/// <summary> | |
/// The data connection string key. | |
/// </summary> | |
private const string DataConnectionStringKey = "DataConnectionString"; | |
/// <summary> | |
/// The storage key. | |
/// </summary> | |
private const string StorageKey = "Storage"; | |
/// <summary> | |
/// The orleans azure silo. | |
/// </summary> | |
private AzureSilo orleansAzureSilo; | |
/// <summary> | |
/// Handle the start event. | |
/// </summary> | |
/// <returns>A value indicating whether or not this role started successfully.</returns> | |
public override bool OnStart() | |
{ | |
if (!Trace.Listeners.OfType<DiagnosticMonitorTraceListener>().Any() && !RoleEnvironment.IsEmulated) | |
{ | |
Trace.Listeners.Add(new DiagnosticMonitorTraceListener()); | |
} | |
// Set the maximum number of concurrent connections | |
ServicePointManager.DefaultConnectionLimit = 12 * Environment.ProcessorCount; | |
// For information on handling configuration changes see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357. | |
RoleEnvironment.Changing += RoleEnvironmentChanging; | |
this.orleansAzureSilo = new AzureSilo(); | |
var ok = base.OnStart(); | |
if (ok) | |
{ | |
var cfg = new ClusterConfiguration(); | |
cfg.LoadFromFile("OrleansConfiguration.xml"); | |
ProviderCategoryConfiguration storageConfiguration; | |
if (cfg.Globals.ProviderConfigurations.TryGetValue(StorageKey, out storageConfiguration)) | |
{ | |
// Find all storage providers with service configuration key names and modify them as necessary. | |
foreach (var provider in storageConfiguration.Providers.Where(provider => provider.Value is ProviderConfiguration)) | |
{ | |
string connectionString; | |
var properties = provider.Value.Properties; | |
if (properties.TryGetValue(DataConnectionStringKey, out connectionString)) | |
{ | |
ModifyProviderProperty( | |
provider.Value as ProviderConfiguration, | |
DataConnectionStringKey, | |
GetConnectionStringFromServiceConfiguration(connectionString)); | |
} | |
} | |
} | |
// Trace ActivityIds should flow between clients and grains. | |
cfg.Defaults.PropagateActivityId = true; | |
// Modify the Azure Liveness ConnectionString as necessary. | |
cfg.Globals.DataConnectionString = GetConnectionStringFromServiceConfiguration(cfg.Globals.DataConnectionString); | |
cfg.Globals.DeploymentId = RoleEnvironment.DeploymentId; | |
ok = this.orleansAzureSilo.Start(RoleEnvironment.DeploymentId, RoleEnvironment.CurrentRoleInstance, cfg); | |
} | |
return ok; | |
} | |
/// <summary> | |
/// Run the silo. | |
/// </summary> | |
public override void Run() | |
{ | |
this.orleansAzureSilo.Run(); // Call will block until silo is shutdown | |
} | |
/// <summary> | |
/// Handle the stop event. | |
/// </summary> | |
public override void OnStop() | |
{ | |
this.orleansAzureSilo.Stop(); | |
RoleEnvironment.Changing -= RoleEnvironmentChanging; | |
base.OnStop(); | |
} | |
/// <summary> | |
/// Sets the <paramref name="property"/> property of <paramref name="provider"/> to <paramref name="newValue"/>. | |
/// </summary> | |
/// <param name="provider">The provider.</param> | |
/// <param name="property">The property.</param> | |
/// <param name="newValue">The new value.</param> | |
private static void ModifyProviderProperty(ProviderConfiguration provider, string property, string newValue) | |
{ | |
// Note: This is obviously not a stable solution | |
var privateProperties = typeof(ProviderConfiguration).GetField("_properties", BindingFlags.NonPublic | BindingFlags.Instance); | |
if (privateProperties != null) | |
{ | |
var properties = (Dictionary<string, string>)privateProperties.GetValue(provider); | |
properties[property] = newValue; | |
} | |
} | |
/// <summary> | |
/// Returns the connection string stored in service configuration given a connection string. | |
/// </summary> | |
/// <param name="originalConnectionString"> | |
/// The original connection string. | |
/// </param> | |
/// <returns> | |
/// The connection string from the service configuration setting indicated by the "ServiceConfigurationSetting" | |
/// parameter of <paramref name="originalConnectionString"/>, or <paramref name="originalConnectionString"/> if | |
/// the parameter is unspecified. | |
/// </returns> | |
/// <remarks> | |
/// Returns <see langword="null"/> if the specified parameter does not indicate a valid setting. | |
/// </remarks> | |
private static string GetConnectionStringFromServiceConfiguration(string originalConnectionString) | |
{ | |
// Default string is returned if setting is invalid. | |
var result = default(string); | |
var settings = originalConnectionString.Split(';') | |
.Select(kvp => kvp.Split('=')) | |
.Where(kvp => kvp.Length == 2) | |
.ToDictionary(kvp => kvp[0], kvp => kvp[1]); | |
string settingName; | |
if (settings.TryGetValue("ServiceConfigurationSetting", out settingName)) | |
{ | |
var connectionString = CloudConfigurationManager.GetSetting(settingName); | |
if (!string.IsNullOrWhiteSpace(connectionString)) | |
{ | |
result = connectionString; | |
} | |
} | |
else | |
{ | |
// Setting was not provided. | |
result = originalConnectionString; | |
} | |
return result; | |
} | |
/// <summary> | |
/// Handle the RoleEnvironmentChanging event. | |
/// </summary> | |
/// <param name="sender"> | |
/// The event sender. | |
/// </param> | |
/// <param name="e"> | |
/// The event arguments. | |
/// </param> | |
private static void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e) | |
{ | |
// If a configuration setting is changing); | |
if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange)) | |
{ | |
// Set e.Cancel to true to restart this role instance | |
e.Cancel = true; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment