This document discusses StateMirror build and installation process in detail. For more information about the product, please visit http://www.statemirror.com.
Copyright (c) 2005-2006 Alfavit. All Rights Reserved.

What's required

.NET Framework 1.1
Make sure you have official release installed (1.1.4322)

.NET Framework 2.0
Make sure you have official release installed (2.0.50727)

gacutil 2.0
Unfortunately, .NET Framework 2.0 does not contain gacutil. It can be found in .NET Framework 2.0 SDK. You have two options: download and install the whole .NET Framework 2.0 SDK, or just borrow gacutil.exe and gacutil.exe.config from it and place them to, say, <StateMirror build dir>\Build\Tools directory.

NAnt 0.85 RC3 or later
According to NAnt developers, NAnt nightly builds support .NET Framework 2.0 starting from March 04, 2006. I did not try nightly builds, but NAnt 0.85 RC3 can build .NET 2.0 binaries if you fix NAnt.exe.config file. Just make sure that the <framework> node with the name "net-2.0" has its properties pointing to the version 2.0.50727 of .NET Framework 2.0:

frameworkdirectory="${path::combine(installRoot, 'v2.0.50727')}" 
frameworkassemblydirectory="${path::combine(installRoot, 'v2.0.50727')}"
clrversion="v2.0.50727"

UpdateVersion utility
UpdateVersion by Matt Griffith is used to calculate new version for daily builds of StateMirror. Download the binary from http:\\mattgriffith.net and place it to, say, <StateMirror build dir>\Build\Tools directory. If you do not want to use UpdateUtitlity for your builds:
- rename all AssemblyInfo.txt files to AssemblyInfo.cs;
- remove all references to UpdateVersion from NAnt build files.

StateMirror build environment

1. Copy StateMirror source file hierarchy to a dedicated directory on your hard drive. We will reference this directory as <StateMirror build dir>.

2. In <StateMirror build dir>\Build directory, create a bldenv.cmd file, that sets PATH variable. Make sure you included the path to NAnt binaries, StateMirror build dir, gacutil 2.0 and UpdateVersion. Here is an example of bldenv.cmd:

@echo Welcome to StateMirror build environment
set path=d:\back\nant\bin\;d:\back\StateMirror\build\;d:\back\StateMirror\build\Tools\;

3. Create a program shortcut called "StateMirror Build Environment"
with target: %windir%\System32\cmd.exe /K <StateMirror build dir>\build\bldenv.cmd
and running in <StateMirror build dir>

Build StateMirror

1. Run "StateMirror Build Environment" program shortcut.

2. Choose a StateMirror component you want to build and go to the correspondent directory. If you want to build all StateMirror binaries, stay in the root StateMirror build directory.

3. Run NAnt build command or use StateMirror shortcuts (you may find them in the Build directory):
d.cmd - build debug (binaries will be copied to bin/Debug directory, shared assemblies added to the GAC)
r.cmd - build release (binaries will be copied to bin/Debug directory, shared assemblies added to the GAC)
c.cmd - clean intermediate build results
cb.cmd - clean bin directory

StateMirror installation

Copy files
On all machines:
- add StateMirror.Core.Dll, StateMirror.Network.Dll, StateMirror.Trace.Dll to the GAC
On the client side (web server machines):
- add StateMirror.SessionStateModule.Dll (.NET 1.1), StateMirror.SessionStateStoreProvider.Dll (.NET 2.0) to the GAC
On the server side (state server machines):
- copy StateMirror.Server.Dll, StateMirror.Service.exe to the local hard drive
On the trace logger machine (optional):
- copy StateMirror.TraceLogService.exe to the local hard drive

Register services
On state server machine:
- register StateMirror service: %windir%\Microsoft.NET\Framework\v2.0.50727\installutil.exe StateMirror.Service.exe
On trace log machine (optional):
- register StateMirror Trace Logger service: %windir%\Microsoft.NET\Framework\v2.0.50727\installutil.exe StateMirror.TraceLogService.exe

Registry settings
On all machines:
- HKLM\Software\Alfavit\StateMirror\Common
-- (required) string LocalIP
-- dword Client2ServerPort
-- dword Server2ClientPort
-- (required) string BroadcastIp
-- dword UdpDatagramLength
-- dword ControlPort

On server machines:
- HKLM\Software\Alfavit\StateMirror\Server
-- dword SrvDeadClientTimeout
-- dword SrvDeadServerTimeout
-- dwordServerHeartBeatInterval

On client machines:
- HKLM\Software\Alfavit\StateMirror\Client
-- (required) string DefaultServers
-- dword UpdateServerInfoPeriod
-- dword MaxTopConnections
-- dword BackLogThreshold
-- dword ClientHeartBeatInterval
-- dword ClientReconnectTimeout
-- dword UseLocalCache
-- dword SkipSavingIdenticalItems
-- dword UpdateCacheOnGet
-- dword CacheCleanupPeriod
-- dword CacheCapacity
-- dword CacheMaxItemStay

On all machines (optional):
- HKLM\Software\Alfavit\StateMirror\Trace
-- dword TracePort
-- dword TraceReconnectTimeout
-- string TraceEventLogMachine
-- dword TraceLevel
-- string TraceLoggerIP

Make sure the values marked as "required" are set properly. Below is the detailed explanation of some important settings.

Communication Settings
Broadcast IP
Registry: Common\BroadcastIp=<broadcast IP address>
Type: string
Used by: Client, Server
Default value: last IP address in the subnet
Unattended setup property: BROADCASTIP

The IP address used by the StateMirror components to communicate between each other. It is strongly recommended to provide a specific IP address for your subnet (e.g.: 192.168.0.255). This allows you to increase the UDP Datagram Length parameter (defaulted to 1500 - the common MTU size) and send data between the Client and Server in bigger blocks that may increase performance. If you set this value to an address that is outside your subnet and increase the UDP datagram length, the datagrams that exceed the MTU size can not be transferred over the network and StateMirror will not function properly. 
Local IP
Registry: Common\LocalIp=<this machine's IP address>
Type: string
Used by: Client, Server
Default value: first NIC IP address found
Unattended setup property: LOCALIP

This value is used by StateMirror Client and Server for demographic purposes. When sending heartbeats, StateMirror Servers and Clients provide this value so the StateMirror Servers and StateMirror Explorer know about each other. If this setting is not valid, then: 
•	StateMirror Explorer trys to report about Clients and Servers that do not actually exist; 
•	Servers with incorrect IP addresses are unavailable. Performance dramatically decreases since Clients keep trying to connect to those Servers; 
This value is especially important when the machine has several network cards installed.
Server-to-client port
Registry: Common\Server2ClientPort=<port used by server to send data to the client>
Type: dword
Used by: Client, Server
Default value: 7125
Unattended setup property: SERVER2CLIENTPORT

This port is used to send data from the Server to Client using TCP connection. 
Client-to-server port
Registry: Common\Client2ServerPort=<port used by client to send data to multiple servers>
Type: dword
Used by: Client, Server
Default value: 7126
Unattended setup property: CLIENT2SERVERPORT

This port is used to send data from the Client to multiple Servers using UDP protocol.
Control Port
Registry: Common\ControlPort=<port used to send control and heartbeat data>
Type: dword
Used by: Client, Server, StateMirror Explorer
Default value: 7127
Unattended setup property: CONTROLPORT

This UDP port is used to send heartbeat data from Client and Server and commands from StateMirror Explorer.
UDP Datagram Length
Registry: Common\UdpDatagramLength=<maximum length of UDP datagram used>
Type: dword
Used by: Client, Server
Default value: 1500 (common MTU size)
Unattended setup property: UDPDATAGRAMLENGTH

The larger the value, the better performance you may get when transferring large objects between StateMirror Client and Server. Most IP implementations do not allow UDP datagrams to be longer than 32k. 
Client Settings
Default Servers
Registry: Common\DefaultServers=<list of IP addresses separated by semicolons>
Type: string
Used by: Client
Default value: none
Unattended setup property: DEFAULTSERVERS

This is the list of Servers that a Client uses:
•	Upon startup; 
•	When all Servers the Client was connected to go offline; 
After connecting to default Servers, the Client gets info about other running Servers from one of these default Servers. This value should never be empty and there must be at least two addresses listed. Server addresses must be separated by semicolons.
Max Top Connections
Registry: Client\MaxTopConnections=<number of the preferred state servers used by client>
Type: dword
Used by: Client
Default value: 2
Unattended setup property: MAXTOPCONNECTIONS

Ideally, this is the total number of a single session state object copies in the system. When one of the Servers goes down, one copy of a session object is lost. The number of copies is increased again when a Client realizes there are too few of them in the system, and engages an additional Server to store an extra copy.
Client Reconnect Timeout
Registry: Client\ClientReconnectTimeout=<timeout to wait when reconnecting to dead servers in milliseconds>
Type: dword
Used by: Client
Default value: 10000
Unattended setup property: CLIENTRECONNECTTIMEOUT

StateMirror Client maintains a list of connection attempt timestamps for every Server. If the Client detects a dead Server, it disconnects from it and next connection attempt may occur only after Client Reconnect Timeout expires. This feature is useful when some StateMirror Servers in the pool are unstable. It also keeps the StateMirror deployment performance at a reasonable rate until the system administrator eliminates the problem with the unstable Server. 
Update ServerInfo Period
Registry: Client\UpdateServerInfoPeriod=<interval in milliseconds, server info refresh frequency>
Type: dword
Used by: Client
Default value: 1000
Unattended setup property: UPDATESERVERINFOPERIOD

This parameter says how often a Client should refresh the list of active Servers. If you want your Clients to react faster on newly added Servers and to engage more Servers as early as possible upon startup, keep this value low. A low value increases the number of Client CPU cycles spent on the transfer.
Client Heartbeat Interval
Registry: Client\ClientHeartBeatInterval=<client heartbeat interval in milliseconds>
Type: dword
Used by: Client
Default value: 3000
Unattended setup property: CLIENTHEARTBEATINTERVAL

Client heartbeat interval. If you are not concerned with real-time client statistics in StateMirror Explorer, you can make this value bigger and reduce the number of CPU cycles on Client side.
Backlog Threshold
Registry: Client\BackLogThreshold=<maximum numer of messages in the message queue>
Type: dword
Used by: Client
Default value: 1024
Unattended setup property: BACKLOGTHRESHOLD

Sets the limit for message queue size.
Use Local Cache
Registry: Client\UseLocalCache=<0 or 1>
Type: dword
Used by: Client
Default value: 1
Unattended setup property: USELOCALCACHE

Tells StateMirror Client if it should cache objects locally. 
Skip Saving Identical Items
Registry: Client\SkipSavingIdenticalItems=<0 or 1>
Type: dword
Used by: Client
Default value: 1
Unattended setup property: SKIPSAVINGIDENTICALITEMS

When storing an existing object to the StateMirror Server, the Client checks its CRC first. If CRCs of the object being saved and the object that is already stored are the same and SkipSavingIdenticalItems flag is 1, StateMirror Client does not overwrite the object on the Server, but marks it as updated. If the value is 0, the Client overwrites the object. 
Update Cache On Get
Registry: Client\UpdateCacheOnGet=<0 or 1>
Type: dword
Used by: Client
Default value: 1
Unattended setup property: UPDATECACHEONGET

If this value is 1 and UseLocalCache is ON, StateMirror Client refreshes its local cache when saving and retrieving items. This setting is especially useful for applications that do not update session object very often. 
Cache Cleanup Period
Registry: Client\CacheCleanupPeriod=<local cache cleanup interval in milliseconds>
Type: dword
Used by: Client
Default value: 10000
Unattended setup property: CACHECLEANUPPERIOD

Tells StateMirror Client how often it should perform cache cleanup and remove expired items. 
Cache Capacity
Registry: Client\CacheCapacity=<maximum number of items in the local cache>
Type: dword
Used by: Client
Default value: 1024
Unattended setup property: CACHECAPACITY

Sets the maximum limit for the number of items in the local cache. This can be useful in large deployments where storing numerous items in the local cache of the web server is unacceptable. 
Cache Max Item Stay
Registry: Client\CacheMaxItemStay=<maximum amount of time that an item can spend in the cache in milliseconds>
Type: dword
Used by: Client
Default value: 60000
Unattended setup property: CACHEMAXITEMSTAY

This setting can be useful in large deployments where session expiration timeout is lengthy and it is too expensive to keep rarely used items. 
Server Settings
Dead Client Timeout
Registry: Server\DeadClientTimeout=<client inactivity timeout in milliseconds, after which the client is considered dead>
Type: dword
Used by: Server
Default value: 15000
Unattended setup property: DEADCLIENTTIMEOUT

After this period of inactivity, the Client is considered dead and the Server closes the corresponding connection.
Dead Server Timeout
Registry: Server\DeadServerTimeout=<server inactivity timeout in milliseconds, after which it is considered dead by other servers>
Type: dword
Used by: Server
Default value: 3000
Unattended setup property: DEADSERVERTIMEOUT

After this period of inactivity, the Server is considered dead by other Servers and they do not advise their Clients to connect to this Server anymore.
Server Heartbeat Interval
Registry: Server\ServerHeartBeatInterval=<server heartbeat interval in milliseconds>
Used by: Server
Default value: 1000
Unattended setup property: SERVERHEARTBEATINTERVAL

Server heartbeat interval. 1000 (one second) is a recommended value.
Trace Settings
Trace Port
Registry: Trace\TracePort=<port used to send trace data>
Type: dword
Used by: Client, Server, Trace Logger Service
Default value: 7128
Unattended setup property: TRACEPORT

This port is used to send trace data from the Server and Client to Trace Logger Service.
Event Log Machine
Registry: Trace\TraceEventLogMachine=<machine name>
Type: string
Used by: Client, Server
Default value: empty
Unattended setup property: TRACEEVENTLOGMACHINE

Specify the machine that will write trace data to the event log. If there is no need to log trace data, set this parameter to empty string or a space.
TraceLogger IP address
Registry: Trace\TraceLoggerIp=<IP address of machine name with Trace Logger Service running>
Type: string
Used by: Client, Server
Default value: empty
Unattended setup property: TRACELOGGERIP

Specify to which machine the trace data is sent. It is strongly recommended to provide a valid address of a machine that runs StateMirror Trace Log service, or leave it empty. Otherwise Clients and Servers may spend large amount of time trying to reconnect to it.
Trace Level
Registry: Trace\TraceLevel=<verbosity level>
Type: dword
Used by: Client, Server
Default value: 3
Unattended setup property: TRACELEVEL

The levels are:
1 - unexpected errors
2 - logical errors, connectivity problems
3 - warnings
4 - info about major events
5 - info about events that happen on regular basis
10 - verbose, do not set this trace level unless you are investigating an issue: it requires a lot of network bandwidth and CPU resources. 
Trace Reconnect Timeout
Registry: Trace\TraceReconnectTimeout=<interval between re-connection attempts in milliseconds>
Type: dword
Used by: Client, Server
Default value: 3000
Unattended setup property: TRACERECONNECTTIMEOUT

If TraceLogger is not available, the next attempt to re-connect and send trace message to it happens only when this timeout expires. This makes things a bit faster when TraceLogger machine unexpectedly goes offline and other StateMirror components are trying to send trace data to the non-existing machine. 

Plugging into ASP.NET

This section briefly discusses how to set up StateMirror as session state manager fro ASP.NET.

ASP.NET 1.1

ASP.NET 1.1 does not allow you to install multiple session state modules. You have to comment out the reference to the standard SessionStateModule from machine.config:

<httpModules>
  ...
  <!-- <add name="Session" type="System.Web.SessionState.SessionStateModule"/> -->
</httpModules>

For those ASP.NET applications that do not use StateMirror, add reference to the standard SessionStateModule to their web.config files:

<httpModules>
  ...
  <add name="Session" type="System.Web.SessionState.SessionStateModule" /> 
</httpModules>

For the applications that use StateMirror for state management, set up their web.config files similarly to the standard ASP.NET state server and:

- Set the connection string to "statemirror" (instead of "tcpip=ip:port");
- Set the trust level to "Full", otherwise the StateMirror components installed in the GAC will be unavailable;
- Add a new module with name "Session" to replace the standard SessionStateModule as follows: 

<system.web>
  ...
  <sessionState mode="StateServer" cookieless="false" timeout="20"
    stateConnectionString="statemirror" />
  <trust level="Full" originUrl="" />
  <httpModules>
    <add name="Session" 
      type="StateMirror.SessionStateModule, StateMirror.SessionStateModule,
      Version=[StateMirror SessionStateModule version], Culture=neutral,
      PublicKeyToken=[StateMirror SessionStateModule token]" />
  </httpModules>
</system.web>

StateMirror 1.0 Beta has version 1.0.6187.0 and public key token "8c973535474f789f". 

ASP.NET 2.0

For ASP.NET 2.0, installation is simple. In web.config file, make <sessionState> section point to StateMirror provider and add StateMirror provider to the list:

<system.web>
  ...
  <sessionState timeout="20" mode="Custom" customProvider="StateMirror SessionStateStoreProvider">
    <providers>
      <add name="StateMirror SessionStateStoreProvider"
        type="StateMirror.SessionStateStoreProvider,
        StateMirror.SessionStateStoreProvider, Version=[StateMirror SessionStateStoreProvider version],
        Culture=neutral, PublicKeyToken=[StateMirror SessionStateStoreProvider token]" />
    </providers>
  </sessionState>
</system.web>

StateMirror 1.0 Beta has version 1.0.6187.0 and public key token "8c973535474f789f".