Create Store Info Cache Write Action

Microsoft.ApplicationServer.CreateStoreInfoCache.WriteAction (WriteActionModuleType)

This write action creates a temporary cache file that is used by the MP to optimize database discovery.

Element properties:

TypeWriteActionModuleType
IsolationAny
AccessibilityPublic
RunAsDefault
InputTypeSystem.BaseData

Member Modules:

ID Module Type TypeId RunAs 
CreateStoreInfoCache.WA WriteAction System.CommandExecuter Default

Overrideable Parameters:

IDParameterTypeSelectorDisplay NameDescription
ClearCacheIntervalDaysint$Config/ClearCacheIntervalDays$Clear Temporary CacheDeletes the temporary cache file used to optimize database discovery.

Source Code:

<WriteActionModuleType ID="Microsoft.ApplicationServer.CreateStoreInfoCache.WriteAction" Accessibility="Public" Batching="false">
<Configuration>
<xsd:element minOccurs="1" name="ClearCacheIntervalDays" type="xsd:integer"/>
</Configuration>
<OverrideableParameters>
<OverrideableParameter ID="ClearCacheIntervalDays" Selector="$Config/ClearCacheIntervalDays$" ParameterType="int"/>
</OverrideableParameters>
<ModuleImplementation Isolation="Any">
<Composite>
<MemberModules>
<WriteAction ID="CreateStoreInfoCache.WA" TypeID="System!System.CommandExecuter">
<ApplicationName>%windir%\system32\windowspowershell\v1.0\powershell.exe</ApplicationName>
<WorkingDirectory/>
<CommandLine>-Command ".\Create-StoreInfoCache.ps1" </CommandLine>
<TimeoutSeconds>600</TimeoutSeconds>
<RequireOutput>true</RequireOutput>
<Files>
<File>
<Name>Create-StoreInfoCache.ps1</Name>
<Contents><Script>


$Error.Clear()
$script:oAPI = new-object -comObject "MOM.ScriptAPI"

#$script:oAPI.LogScriptEvent("Get-ConnectionStringInfoObjects.ps1", 123, 4, "Init")

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Web.Administration")

function Get-ConnectionString
{
Param([string]$connectionStringName, [string]$siteName, [string]$virtualPath)
$DefaultRuntimeVersion = "4.0"
$ConnectionStringsSectionName = 'connectionStrings'
$NameAttributeName = 'name'
$ConnectionStringsAttributeName = 'connectionString'

[string]$connectionString = $null;
$serverManager = new-object Microsoft.Web.Administration.ServerManager
[Microsoft.Web.Administration.Configuration]$webConfig = Get-WebConfiguration -serverManager $serverManager -siteName $siteName -virtualPath $virtualPath

$webConfig.SetMetadata("defaultManagedRuntimeVersion", $DefaultRuntimeVersion);

[Microsoft.Web.Administration.ConfigurationSection]$connectionStringSection = $webConfig.GetSection($ConnectionStringsSectionName)
[Microsoft.Web.Administration.ConfigurationElementCollection]$connectionStringCollection = $connectionStringSection.GetCollection()
if ($connectionStringCollection -ne $null)
{
foreach ($connectionStringElement in $connectionStringCollection)
{
[string]$name = $connectionStringElement.GetAttributeValue($NameAttributeName)
if ((![string]::IsNullOrEmpty($name)) -and ($name.CompareTo($connectionStringName) -eq 0))
{
$connectionString = $connectionStringElement.GetAttributeValue($ConnectionStringsAttributeName)
break
}
}
}

return $connectionString

trap [Exception]
{
if ($script:oAPI -ne $null)
{
foreach($errorDetail in $Error)
{
$script:oAPI.LogScriptEvent('Get-ConnectionStringInfoObjects.ps1', 101, 1, $errorDetail.Exception)
Write-Host $errorDetail.Exception
}
}

return $null
}
}

function Get-WebConfiguration
{
Param($serverManager, [string]$siteName, [string]$virtualPath)

[Microsoft.Web.Administration.Configuration]$webConfig = $null;
if ([string]::IsNullOrEmpty($siteName) -and [string]::IsNullOrEmpty($virtualPath))
{
$webConfig = $serverManager.GetWebConfiguration($null);
}
elseif (![string]::IsNullOrEmpty($siteName))
{

if ([string]::IsNullOrEmpty($virtualPath))
{
$virtualPath = '/'
}

$webConfig = $serverManager.GetWebConfiguration($siteName, $virtualPath)
}
else
{
throw "Invalid configuration at " + $siteName + "/" + $virtualPath;
}

return $webConfig;
}

function Get-SHA1Hash
{
param([string]$stringValueToHash)
$hashAlgorithm = new-object System.Security.Cryptography.SHA1Managed
$computedHashBytes = $hashAlgorithm.ComputeHash($([Char[]]$stringValueToHash.ToUpperInvariant()));

$stringBuilder = New-Object System.Text.StringBuilder
$computedHashBytes | Foreach-Object { [void] $stringBuilder.Append($_.ToString("X2")) }
return $stringBuilder.ToString()
}

function Get-DBInfo
{
Param([string]$connectionString, [string]$providerName)

$dbFactory = [System.Data.Common.DbProviderFactories]::GetFactory("$providerName");
[System.Data.Common.DbConnection]$dbConnection = $dbFactory.CreateConnection()
$dbConnection.ConnectionString = $connectionString
[Hashtable]$dbInfo = $null

.{
$dbConnection.Open()
$dbCommand = $dbConnection.CreateCommand()

$dbCommand.CommandText = "IF EXISTS(Select 1 from sysobjects WHERE name = 'ASDBVersion') SELECT 1 ELSE SELECT 0"
if ($dbCommand.ExecuteScalar() -eq 1)
{
$dbCommand.CommandText = "SELECT * FROM [ASDBVersion]"

[System.Data.Common.DbDataReader]$dbReader = $dbCommand.ExecuteReader()
if($dbReader.HasRows -and $dbReader.Read())
{
$dbInfo = @{DbIdentity = $dbReader.GetValue($dbReader.GetOrdinal('DbIdentity')); PDbIdentity = [string]::Empty; DataSource = $dbConnection.DataSource; Database = $dbConnection.Database; Provider = $providerName;}
$dbReader.Dispose()
}
}

$dbCommand.CommandText = "IF EXISTS(Select 1 from sysobjects WHERE name = 'StoreVersion') SELECT 1 ELSE SELECT 0"
if ($dbCommand.ExecuteScalar() -eq 1)
{
$dbCommand.CommandText = "SELECT * FROM [Microsoft.ApplicationServer.DurableInstancing].[StoreVersion]"

[System.Data.Common.DbDataReader]$dbReader = $dbCommand.ExecuteReader()
if($dbReader.HasRows -and $dbReader.Read())
{
if ($dbInfo -eq $null)
{
$dbInfo = @{DbIdentity = [string]::Empty; PDbIdentity = $dbReader.GetValue($dbReader.GetOrdinal('StoreIdentifier')); DataSource = $dbConnection.DataSource; Database = $dbConnection.Database; Provider = $providerName;}
}
else
{
$dbInfo['PDbIdentity'] = $dbReader.GetValue($dbReader.GetOrdinal('StoreIdentifier'))
}

$dbReader.Dispose()
}
}
}

trap [Exception]
{
Write-host $_.Exception.Message
$script:oAPI.LogScriptEvent("Create-StoreInfoCache.ps1", 201, 2, $_.Exception)
continue
}

if ($dbInfo -eq $null)
{
$dbInfo = @{DbIdentity = $null; PDbIdentity = $null; DataSource = $dbConnection.DataSource; Database = $dbConnection.Database; Provider = $providerName;}
}

# free resources
if ($dbConnection -ne $null)
{
$dbConnection.Dispose()
}

return $dbInfo
}

if ((Get-Command -Module ApplicationServer) -eq $null)
{
Import-Module ApplicationServer # Application Server Extensions for .NET 4
}

if ((Test-Path "$env:ALLUSERSPROFILE\Microsoft AppFabric Management Pack\") -eq $false)
{
New-Item "$env:ALLUSERSPROFILE\Microsoft AppFabric Management Pack\" -type directory
}

$connectionStringInfoObjects = Get-ASApplication | Get-ASAppMonitoring | where {$_.ProviderName -match "System.Data.SqlClient"} | Group-Object ConnectionString -ErrorAction SilentlyContinue
[Hashtable]$currentDbInfoCache = New-Object Hashtable

if($connectionStringInfoObjects -ne $null)
{
foreach ($connectionStringInfoObject in $connectionStringInfoObjects)
{
[string]$currentCunnectionString = $connectionStringInfoObject.Group[0].ConnectionString
[string]$hashedCurrentCunnectionString = Get-SHA1Hash -stringValueToHash $currentCunnectionString
$dbInfo = @{DbIdentity = $null; DataSource = $null; Database = $null; ConnectionString = $currentCunnectionString; Provider = $connectionStringInfoObject.Group[0].ProviderName; Locations = New-Object System.Collections.ArrayList;}
foreach ($group in $connectionStringInfoObject.Group)
{
$count = $dbInfo.Locations.Add(@($group.SiteName, $group.VirtualPath))
}

$currentDbInfoCache[$hashedCurrentCunnectionString] = $dbInfo
}
}
else
{
$script:oAPI.LogScriptEvent('Get-ConnectionStringInfoObjects.ps1', 200, 2, 'Unable to fetch any Monitoring Store connection string info objects')
}

# Get all Persistence store information
$instanceStoreInfoObjects = Get-AsApplication | Get-ASAppInstanceStore | where {$_.ProviderName -match "SqlPersistenceStoreProvider"} | Group-Object SiteName, VirtualPath -ErrorAction SilentlyContinue
if($instanceStoreInfoObjects -ne $null)
{
foreach ($instanceStoreInfoObject in $instanceStoreInfoObjects)
{
$parameters = $instanceStoreInfoObject.Group[0].Parameters
$connectionString = $null
if ($parameters.Get('connectionString') -ne $null)
{
$connectionString = $parameters.Get('connectionString')
}
elseif ($parameters.Get('connectionStringName') -ne $null)
{
$connectionString = Get-ConnectionString -connectionStringName $parameters.Get('connectionStringName') -siteName $instanceStoreInfoObject.Group[0].SiteName -virtualPath $instanceStoreInfoObject.Group[0].VirtualPath
}

if ($connectionString -ne $null)
{
[string]$hashedCurrentCunnectionString = Get-SHA1Hash -stringValueToHash $connectionString
if(!$currentDbInfoCache.Contains($hashedCurrentCunnectionString))
{
$dbInfo = @{DbIdentity = $null; DataSource = $null; Database = $null; ConnectionString = $connectionString; Provider = 'System.Data.SqlClient'; Locations = New-Object System.Collections.ArrayList;}
$dbInfo.Locations.Add(@($instanceStoreInfoObject.Group[0].SiteName, $instanceStoreInfoObject.Group[0].VirtualPath))
$currentDbInfoCache[$hashedCurrentCunnectionString] = $dbInfo
}
}
}
}
else
{
$script:oAPI.LogScriptEvent('Get-ConnectionStringInfoObjects.ps1', 200, 2, 'Unable to fetch any Persistence connection string info objects')
}

# Create Store Info Cache
#$script:oAPI.LogScriptEvent("Create-StoreInfoCache.ps1", 123, 4, "Init")
[string]$DbInfoCacheFileName = "$env:ALLUSERSPROFILE\Microsoft AppFabric Management Pack\DbInfoCache.xml"

[Hashtable]$existingDbInfoCache = $null
if(test-path $DbInfoCacheFileName)
{
#clear cache if older than 'X' days
$CreationTime = (Get-Item $DbInfoCacheFileName).CreationTime
$timeDiff = new-timespan $CreationTime (get-Date)
if ($timeDiff.Days -gt $Config/ClearCacheIntervalDays$)
{
Remove-Item -Path $DbInfoCacheFileName
}
else
{
$existingDbInfoCache = Import-Clixml -Path $DbInfoCacheFileName
}
}

$connectionStringInfoObjects = $currentDbInfoCache

[Hashtable]$currentDbInfoCache = New-Object Hashtable
foreach ($connectionStringKey in $connectionStringInfoObjects.Keys)
{
[Hashtable]$dbInfo = $null
if ($existingDbInfoCache -ne $null -and
$existingDbInfoCache.Contains($connectionStringKey) -and
($existingDbInfoCache[$connectionStringKey].DbIdentity -ne $null -and $existingDbInfoCache[$connectionStringKey].PDbIdentity -ne $null))
{
$dbInfo = $existingDbInfoCache[$connectionStringKey]
}
else
{
[string]$currentCunnectionString = $connectionStringInfoObjects[$connectionStringKey].ConnectionString
[string]$currentProvider = $connectionStringInfoObjects[$connectionStringKey].Provider
$dbInfo = Get-DBInfo -connectionString $currentCunnectionString -providerName $currentProvider
$dbInfo['Locations'] = $connectionStringInfoObjects[$connectionStringKey].Locations
}

$currentDbInfoCache[$connectionStringKey] = $dbInfo
}

Export-Clixml -Path $DbInfoCacheFileName -InputObject $currentDbInfoCache
return

trap
{
if ($oAPI -ne $null)
{
foreach($errorDetail in $Error)
{
$script:oAPI.LogScriptEvent("Create-StoreInfoCache.ps1", 100, 1, $errorDetail.Exception)
}
}

return
}


</Script></Contents>
<Unicode>1</Unicode>
</File>
</Files>
</WriteAction>
</MemberModules>
<Composition>
<Node ID="CreateStoreInfoCache.WA"/>
</Composition>
</Composite>
</ModuleImplementation>
<InputType>System!System.BaseData</InputType>
</WriteActionModuleType>