The HashRing implementation as a generic class
//Fields SortedDictionary<UInt32, HashRingLocation<T>> _locations; //Properties private SortedDictionary<UInt32, HashRingLocation<T>> LocationDictionary { get { _locations = _locations ?? new SortedDictionary<uint, HashRingLocation<T>>(); return _locations; } } public List<HashRingLocation<T>> Locations { get { return LocationDictionary.Values.ToList() /// The locations collection; } } //Public Methods for Location public void AddLocation(T item) { item.ThrowIfNull(); UInt32 key = Hashing.HashItem(item); HashRingLocation<T> location = new HashRingLocation<T>(key, item); LocationDictionary.Add(key, location); var ndx = LocationDictionary.IndexOfKey(key); var fromNdx = ndx < LocationDictionary.Count - 1 ? ndx + 1 : ndx; var fromLocation = LocationDictionary.ElementAt(fromNdx).Value; List<UInt32> keysToRemove = new List<uint>(); foreach (var node in fromLocation.NodeDictionary.Where(n => n.Key <= key)){ keysToRemove.Add(node.Key); location.NodeDictionary.Add(node.Key, node.Value); } foreach(var removekey in keysToRemove){ fromLocation.NodeDictionary.Remove(removekey); } } //Public Methods for Items public void AddItem(T item) { item.ThrowIfNull(); bool putInlastNode = true; UInt32 key = Hashing.HashItem(item); HashRingNode<T> node = new HashRingNode<T>() { Key = key, Item = item }; foreach(var locationKey in LocationDictionary.Keys){ if(key < locationKey){ // Check for key collision if (LocationDictionary[locationKey].NodeDictionary.ContainsKey(key)) { var checkNode = LocationDictionary[locationKey].NodeDictionary[key].Next; while (checkNode != null) { checkNode = checkNode.Next; } LocationDictionary[locationKey].DuplicateCount++; checkNode = new HashRingNode<T>() { Key = key, Item = item }; } else{ LocationDictionary[locationKey].NodeDictionary.Add(key, node); } putInlastNode = false; break; } } if(putInlastNode && LocationDictionary.Count > 0){ LocationDictionary.ElementAt(LocationDictionary.Count - 1).Value.NodeDictionary.Add(key, node); } } public void RemoveItem(T item) { item.ThrowIfNull(); UInt32 key = Hashing.HashItem(item); HashRingLocation<T> foundLocation = null; foreach (var locationKey in LocationDictionary.Keys){ if (key < locationKey) { foundLocation = LocationDictionary[locationKey]; break; } } if(foundLocation != null && foundLocation.NodeDictionary.ContainsKey(key)){ foundLocation.NodeDictionary.Remove(key); } }
// Is there a location for this item public bool HasLocation(T item) { item.ThrowIfNull(); UInt32 key = Hashing.HashItem(item); return LocationDictionary.ContainsKey(key); } // How many locations does this HashRing have public int LocationCount { get { return LocationDictionary.Count; } } // Get the location for the index public HashRingLocation<T> LocationAt(int index) { return LocationDictionary.ElementAt(index).Value; } // Get the index for the location item public int LocationIndexFor(T item) { item.ThrowIfNull(); UInt32 key = Hashing.HashItem(item); return LocationDictionary.IndexOfKey(key); }