internal ulong[] GetPointsForMember(string membersKey) { ulong[] points = new ulong[_numberOfPointsOnRingForEachMember]; ulong initialHash = _baseHashFunction.Hash(membersKey, UniversalHashFunction.MaximumNumberOfResultBitsAllowing32BiasedBits); for (int i = 0; i < points.Length; i++) { points[i] = _universalHashFunctionsForEachPoint[i].Hash(initialHash, UniversalHashFunction.MaximumNumberOfResultBitsAllowing32BiasedBits); } return(points); }
/// <summary> /// Map a element to its corresponding bits in the array. /// </summary> /// <param name="element">The element to be mapped to indexes</param> /// <param name="numberOfIndexesRequested">The number of indexes to associate with the element. If not set, /// uses the MaximumBitIndexesPerElement specified in the constructor.</param> /// <returns>The array indexes associated with the element.</returns> public IEnumerable <int> GetIndexesAssociatedWithAnElement(byte[] element, int?numberOfIndexesRequested = null) { // Build a set of indexes into the bit array associated with the element HashSet <int> indexesIntoBitArray = new HashSet <int>(); // Determine how many indexes to generate for this element. // The lesser of the maximum number supported and the number requested (if provided) int numberOfBitIndexesToCreate = Math.Min(HashFunctionsMappingElementsToBitsInTheArray.Length, numberOfIndexesRequested ?? int.MaxValue); // Use one hash function to generate each index for (int i = 0; i < numberOfBitIndexesToCreate; i++) { UniversalHashFunction hashFunction = HashFunctionsMappingElementsToBitsInTheArray[i]; byte[] valueToHash = ManagedSHA256.Hash(element); do { // Use the hash function to index into the array of bits int indexIntoBitArray = (int)(hashFunction.Hash(valueToHash) % (uint)Length); if (indexesIntoBitArray.Add(indexIntoBitArray)) { // Common case: this index points to a bit that is not yet associated with the element // This index can thus represent the i_th bit for this element. break; } // This hash function generated an index to a bit that is already associated with this element. // We'll need to rehash to create an index for the i_th bit that was not already assigned. valueToHash = ManagedSHA256.Hash(valueToHash); } while (true); } return(indexesIntoBitArray); }
public void UniversalHashTestBias() { Pseudorandom pseudo = new Pseudorandom(); UniversalHashFunction f = new UniversalHashFunction("Louis Tully as played by Rick Moranis!"); ulong trials = 100000000; ulong[] bitCounts = new ulong[64]; for (ulong trial = 0; trial < trials; trial++) { string randomString = pseudo.GetString(8); UInt64 supposedlyUnbiasedBits = f.Hash(randomString, UniversalHashFunction.MaximumNumberOfResultBitsAllowing32BiasedBits); for (int bit = 0; bit < bitCounts.Length; bit++) { if ((supposedlyUnbiasedBits & (0x8000000000000000ul >> bit)) != 0ul) { bitCounts[bit]++; } } } double[] biases = bitCounts.Select(count => ((0.5d - (((double)count) / ((double)trials)))) / 0.5d).ToArray(); /// The first 32 bits should be unbiased for (int bit = 0; bit < 32; bit++) { double bias = biases[bit]; double biasAbs = Math.Abs(bias); Assert.True(biasAbs < 0.0005d); } }
/// <summary> /// Map a member to a set of NumberOfPointsOnRingForEachMember points. /// </summary> /// <param name="membersKey">The key of the member to get the ring points for.</param> /// <returns>An array of points of length NumberOfPointsOnRingForEachMember.</returns> internal ulong[] GetPointsForMember(string membersKey) { // Allocate the array ulong[] points = new ulong[_numberOfPointsOnRingForEachMember]; // Calculate a initial hash of the string (with time linear in the size of the string) ulong initialHash = _baseHashFunction.Hash(membersKey, UniversalHashFunction.MaximumNumberOfResultBitsAllowing32BiasedBits); // Generate each point by re-hashing the initial hash value using a constant-time // universal hash function (since the initial hash is constant size: a 64-bit UInt). for (int i = 0; i < points.Length; i++) { // Points[i] = UniversalHashFunctionsForEachPoint[i].Hash(Member.ToString(), UniversalHashFunction.MaximumNumberOfResultBitsAllowing32BiasedBits); points[i] = _universalHashFunctionsForEachPoint[i].Hash(initialHash, UniversalHashFunction.MaximumNumberOfResultBitsAllowing32BiasedBits); } // Return the set of points. return(points); }
public TMemberType FindMemberResponsible(string key) { TMemberType highestScoringMember = default(TMemberType); ulong highestScore = 0; UInt32 intermediateHashValue = (UInt32)_baseHashFunction.Hash(key); MemberAndItsHashFunction[] localMembersAndTheirHashFunctions = MembersAndTheirHashFunctionsAsArray; foreach (MemberAndItsHashFunction memberAndHash in localMembersAndTheirHashFunctions) { ulong score = memberAndHash.HashFunction.Hash(intermediateHashValue, UniversalHashFunction.MaximumNumberOfResultBitsAllowing32BiasedBits); if (score > highestScore) { highestScore = score; highestScoringMember = memberAndHash.Member; } } return(highestScoringMember); }
public List <TMemberType> FindMembersResponsible(string key, int numberOfUniqueMembersToFind) { TMemberType[] highestScoringMembers = new TMemberType[numberOfUniqueMembersToFind]; ulong[] highestScores = new ulong[numberOfUniqueMembersToFind]; UInt32 intermediateHashValue = (UInt32)_baseHashFunction.Hash(key); MemberAndItsHashFunction[] localMembersAndTheirHashFunctions = MembersAndTheirHashFunctionsAsArray; foreach (MemberAndItsHashFunction memberAndHash in localMembersAndTheirHashFunctions) { TMemberType member = memberAndHash.Member; UniversalHashFunction hashFunction = memberAndHash.HashFunction; ulong score = hashFunction.Hash(intermediateHashValue, UniversalHashFunction.MaximumNumberOfResultBitsAllowing32BiasedBits); int indexToWriteInto; for (indexToWriteInto = numberOfUniqueMembersToFind; indexToWriteInto >= 1 && score > highestScores[indexToWriteInto - 1]; indexToWriteInto--) { } while (indexToWriteInto < numberOfUniqueMembersToFind) { TMemberType evictedMember = highestScoringMembers[indexToWriteInto]; ulong evictedScore = highestScores[indexToWriteInto]; highestScoringMembers[indexToWriteInto] = member; highestScores[indexToWriteInto] = score; indexToWriteInto++; member = evictedMember; score = evictedScore; } } List <TMemberType> result = new List <TMemberType>(numberOfUniqueMembersToFind); for (int i = 0; i < numberOfUniqueMembersToFind && !highestScoringMembers[i].Equals(default(TMemberType)); i++) { result.Add(highestScoringMembers[i]); } return(result); }
protected void AddInsideLock(string physicalNode) { if (!PhysicalNodeToNodeRelationships.ContainsKey(physicalNode)) { NodeRelationshipScore[] nodeRelationshipScores = new NodeRelationshipScore[NumberOfVirtualNodes]; UniversalHashFunction hash = new UniversalHashFunction(ConfigurationKey + physicalNode); for (int i = 0; i < NumberOfVirtualNodes; i++) { nodeRelationshipScores[i].PhysicalNode = physicalNode; nodeRelationshipScores[i].VirtualNode = i; nodeRelationshipScores[i].Score = hash.Hash(i); } } foreach (NodeRelationshipScore nrs in PhysicalNodeToNodeRelationships[physicalNode]) { SortedNodeRelationshipScores.Add(nrs); } PhysicalNodes.Add(physicalNode); }
public IEnumerable <int> GetIndexesAssociatedWithAnElement(byte[] element, int?numberOfIndexesRequested = null) { HashSet <int> indexesIntoBitArray = new HashSet <int>(); int numberOfBitIndexesToCreate = Math.Min(HashFunctionsMappingElementsToBitsInTheArray.Length, numberOfIndexesRequested ?? int.MaxValue); for (int i = 0; i < numberOfBitIndexesToCreate; i++) { UniversalHashFunction hashFunction = HashFunctionsMappingElementsToBitsInTheArray[i]; byte[] valueToHash = ManagedSHA256.Hash(element); do { int indexIntoBitArray = (int)(hashFunction.Hash(valueToHash) % (uint)Length); if (indexesIntoBitArray.Add(indexIntoBitArray)) { break; } valueToHash = ManagedSHA256.Hash(valueToHash); } while (true); } return(indexesIntoBitArray); }
public int GetShardIndex(string key) => (int)(ShardHashFunction.Hash(key) % (uint)NumberOfShards);
public uint FindVirtualNodeResponsible(string key) { ulong virtualNode = KeyHash.Hash(key) % (ulong)NumberOfVirtualNodes; return((uint)virtualNode); }