In bridge topology, there can be more than one active site cache and cache operations can be simultaneous. It is possible that the client connected with one active site cache adds some keys and the same key operation is performed by the other active node. In such a situation the bridge conflict resolver comes into play. It resolves the conflicts and decides which key to apply on the cache depending upon the defined rules.
If user hasn't configured any conflict resolver rules, then NCache uses the default resolver rule. In the default rule, a timespan is added with each operation performed on the cache and it keeps the latest operation. A check is performed on the version of the bridge item. If it has a newer time stamp or if the version is the latest or the same it replaces that with the new entry and in case of old, it keeps the old entry.
Using Bridge Conflict Resolver
Namespace
For enabling Bridge Conflict Resolver, your program needs a reference to the assembly Alachisoft.NCache.Runtime.dll that contains interface Alachisoft.NCache.Runtime.Bridge.IBridgeConflictResolver provided by NCache. The class implementing this interface allows framework to resolve the conflict between existing operations and operation replicated from bridge to cache. Thus, the class needs to include the logic for Conflict Resolution between bridge and cache.
Following namespace is required in your project for using IBridgeConflictResolver:
using Alachisoft.NCache.Runtime.Bridge;
IBridgeConflictResolver Interface:
In order to use IBridgeConflictResolver in your application, implement the following interface:
public void Init(System.Collections.IDictionary parameters);
public ConflictResolution Resolve(ProviderBridgeItem oldEntry, ProviderBridgeItem newEntry);
public void Dispose();
Method
|
Description
|
void Init (IDictionary parameters)
|
This method performs tasks like allocating resources, acquiring connections etc. When cache is initialized and Conflict Resolvers is enabled, Init method is called to notify the client that cache is initializing and the client can initialize its conflict resolver via Init. The parameters passed as an argument contains all the parameters (if any) that were specified using NCache Manager cache/cluster views. These parameters can be utilized in many ways.
|
void Dispose();
|
This method performs tasks like releasing the resources etc. When Cache is stopped or the task is completed, it calls the Dispose() method to notify the client that it can now free the resources related to its task.
|
ConflictResolution Resolve (ProviderBridgeItemoldEntry, ProviderBridgeItemnewEntry);
|
This method contains the logic to resolve the conflict occur while replicating an operation from bridge for a key that already exists in the cache. Whenever any conflict occurs, cache call BridgeConflictResolution to decides which operation to apply on the cache depending upon rules implemented in it. It takes two parameters/entries, both are of ProviderBridgeItem type. ProviderBridgeItem contains the following parameters:
· BridgeItemVersion contains version of an item (LATEST, OLD, SAME).
· Key contains key of an item.
· Value of an item contains value of an item.
· BridgeItemOpCodes contains conflicted operation (Add, Remove, Update, Clear, RemoveGroup,RegisterKeyNotificationetc) .
|
Implementing Bridge Conflict Resolver
Here is a sample implementation for IBridgeConflictResolver:
public class Resolver : Alachisoft.NCache.Runtime.Bridge.IBridgeConflictResolver
{
//
// If true, logs will be generated
//
private bool _enableLogging;
private TextWriter _textLogger;
public void Dispose()
{
if (_enableLogging)
{
_textLogger.WriteLine("Closing logger");
_textLogger.Close();
}
}
public void Init(System.Collections.IDictionary parameters)
{
//
//Initialize textWriter
//
if (parameters.Contains("logging"))
{
_enableLogging = Convert.ToBoolean(parameters["logging"]);
}
if (_enableLogging)
{
_textLogger = new StreamWriter("bridgeResolverLog.txt");
_textLogger.WriteLine("Initializing bridge Conflict Resolver");
}
}
public ConflictResolution Resolve(ProviderBridgeItem oldEntry, ProviderBridgeItem newEntry)
{
ConflictResolution conflictResolution = new ConflictResolution();
switch (oldEntry.BridgeItemVersion)
{
case BridgeItemVersion.OLD:
{
conflictResolution.ResolutionAction = ResolutionAction.ReplaceWithNewEntry;
}
break;
case BridgeItemVersion.LATEST:
{
conflictResolution.ResolutionAction = ResolutionAction.KeepOldEntry;
}
break;
case BridgeItemVersion.SAME:
{
if (oldEntry.OpCode == BridgeItemOpCodes.Remove)
{
conflictResolution.ResolutionAction = ResolutionAction.ReplaceWithNewEntry;
}
else
{
conflictResolution.ResolutionAction = ResolutionAction.KeepOldEntry;
}
}
break;
}
if (_enableLogging)
_textLogger.WriteLine("Resolve Key {0} and decision taken {1}", oldEntry.Key, conflictResolution.ResolutionAction.ToString());
return conflictResolution;
}
}
See Also