Skip to content

Commit

Permalink
NCBC-659: Make KetamaKeyMapper and VBucketKeyMapper Dispose HashAlgor…
Browse files Browse the repository at this point in the history
…ithm after every use

Change-Id: I33ba2b21789713069f06211c1f353698ff4f771a
Reviewed-on: http://review.couchbase.org/41779
Tested-by: Jeffry Morris <jeffrymorris@gmail.com>
Reviewed-by: Brett Lawson <brett19@gmail.com>
  • Loading branch information
jeffrymorris committed Sep 30, 2014
1 parent 887747e commit 28af3d9
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 82 deletions.
4 changes: 2 additions & 2 deletions Src/Couchbase.Tests/Core/Buckets/MemcachedBucketTests.cs
Expand Up @@ -18,7 +18,7 @@ public class MemcachedBucketTests
{
private ICouchbaseCluster _cluster;

[TestFixtureSetUp]
[SetUp]
public void SetUp()
{
_cluster = new Cluster();
Expand Down Expand Up @@ -415,7 +415,7 @@ public void Test_Multi_Upsert()
}
}

[TestFixtureTearDown]
[TearDown]
public void TestFixtureTearDown()
{
_cluster.Dispose();
Expand Down
21 changes: 0 additions & 21 deletions Src/Couchbase.Tests/Core/Buckets/VBucketKeyMapperTests.cs
Expand Up @@ -42,27 +42,6 @@ public void TestMapKey()
Assert.IsNotNull(vBucket);
}

[Test]
public void Test_That_HashAlgorithm_Is_Not_Null()
{
IKeyMapper mapper = new VBucketKeyMapper(_servers, _vBucketServerMap);
Assert.IsNotNull(mapper.HashAlgorithm);
}

[Test]
public void Test_That_HashAlgorithm_Default_Type_Is_Crc32()
{
IKeyMapper mapper = new VBucketKeyMapper(_servers, _vBucketServerMap);
Assert.IsInstanceOf<Crc32>(mapper.HashAlgorithm);
}

[Test]
public void Test_That_HashAlgorithm_Default_Type_Can_Be_Overridden()
{
IKeyMapper mapper = new VBucketKeyMapper(new HMACMD5(), _servers, _vBucketServerMap);
Assert.IsInstanceOf<HMACMD5>(mapper.HashAlgorithm);
}

[Test(Description = "Note, will probably only work on localhost")]
public void Test_That_Key_XXXXX_Maps_To_VBucket_389()
{
Expand Down
47 changes: 21 additions & 26 deletions Src/Couchbase/Core/Buckets/KetamaKeyMapper.cs
Expand Up @@ -15,19 +15,13 @@ internal class KetamaKeyMapper : IKeyMapper
private readonly int _totalWeight;
private readonly SortedDictionary<long, IServer> _buckets = new SortedDictionary<long, IServer>();

public KetamaKeyMapper(List<IServer> servers)
: this(servers, MD5.Create())
{
}

public KetamaKeyMapper(List<IServer> servers, HashAlgorithm algorithm)
public KetamaKeyMapper(List<IServer> servers)
{
_servers = servers;
_totalWeight = _servers.Count;
HashAlgorithm = algorithm;
Initialize();
}

/// <summary>
/// Maps a Key to a node in the cluster.
/// </summary>
Expand Down Expand Up @@ -77,12 +71,15 @@ public int FindIndex(long key)
public long GetHash(string key)
{
var bytes = Encoding.UTF8.GetBytes(key);
var hash = HashAlgorithm.ComputeHash(bytes);
var result = ((long) (hash[3] & 0xFF) << 24)
| ((long)(hash[2] & 0xFF) << 16)
| ((long)(hash[1] & 0xFF) << 8)
| (uint)hash[0] & 0xFF;
return result;
using (var md5 = MD5.Create())
{
var hash = md5.ComputeHash(bytes);
var result = ((long) (hash[3] & 0xFF) << 24)
| ((long) (hash[2] & 0xFF) << 16)
| ((long) (hash[1] & 0xFF) << 8)
| (uint) hash[0] & 0xFF;
return result;
}
}

/// <summary>
Expand All @@ -98,25 +95,23 @@ public void Initialize()
for (long n = 0; n < factor; n++)
{
var bytes = Encoding.UTF8.GetBytes(server.EndPoint + "-" + n);
var hash = HashAlgorithm.ComputeHash(bytes);
for (var j = 0; j < 4; j++)
using (var md5 = MD5.Create())
{
var key = ((long) (hash[3 + j*4] & 0xFF) << 24)
| ((long) (hash[2 + j*4] & 0xFF) << 16)
| ((long) (hash[1 + j*4] & 0xFF) << 8)
| (uint) (hash[0 + j*4] & 0xFF);
var hash = md5.ComputeHash(bytes);
for (var j = 0; j < 4; j++)
{
var key = ((long) (hash[3 + j*4] & 0xFF) << 24)
| ((long) (hash[2 + j*4] & 0xFF) << 16)
| ((long) (hash[1 + j*4] & 0xFF) << 8)
| (uint) (hash[0 + j*4] & 0xFF);

_buckets[key] = server;
_buckets[key] = server;
}
}
}
}
}

/// <summary>
/// The alogrithm for hashing the keys.
/// </summary>
public HashAlgorithm HashAlgorithm { get; set; }

public int Rev { get; set; }
}
}
Expand Down
37 changes: 9 additions & 28 deletions Src/Couchbase/Core/Buckets/VBucketKeyMapper.cs
Expand Up @@ -20,30 +20,13 @@ internal class VBucketKeyMapper : IKeyMapper
private readonly VBucketServerMap _vBucketServerMap;
private readonly List<IServer> _servers;

public VBucketKeyMapper(List<IServer> servers, VBucketServerMap vBucketServerMap)
: this(new Crc32(), servers, vBucketServerMap)
public VBucketKeyMapper(List<IServer> servers, VBucketServerMap vBucketServerMap)
{
}

public VBucketKeyMapper(HashAlgorithm algorithm, List<IServer> servers, VBucketServerMap vBucketServerMap)
{
HashAlgorithm = algorithm;
_servers = servers;
_vBucketServerMap = vBucketServerMap;
_vBuckets = CreateVBucketMap();
_vForwardBuckets = CreateVBucketMapForwards();
}

public VBucketKeyMapper(HashAlgorithm algorithm, Dictionary<int, IVBucket> vBuckets)
{
HashAlgorithm = algorithm;
_vBuckets = vBuckets;
}

public VBucketKeyMapper(Dictionary<int, IVBucket> vBuckets)
: this(new Crc32(), vBuckets)
{
}

/// <summary>
/// Maps a given Key to it's node in a Couchbase Cluster.
Expand All @@ -57,17 +40,15 @@ public IMappedNode MapKey(string key)
return _vBuckets[index];
}

/// <summary>
/// The alogrithm for hashing the keys. Couchbase Buckets use CRC32.
/// </summary>
public HashAlgorithm HashAlgorithm { get; set; }

public int GetIndex(string key)
{
var keyBytes = Encoding.UTF8.GetBytes(key);
var hashedKeyBytes = HashAlgorithm.ComputeHash(keyBytes);
var hash = BitConverter.ToUInt32(hashedKeyBytes, 0);
return (int)hash & Mask;
using (var crc32 = new Crc32())
{
var keyBytes = Encoding.UTF8.GetBytes(key);
var hashedKeyBytes = crc32.ComputeHash(keyBytes);
var hash = BitConverter.ToUInt32(hashedKeyBytes, 0);
return (int)hash & Mask;
}
}

/// <summary>
Expand All @@ -79,7 +60,7 @@ public int GetIndex(string key)
var vBuckets = new Dictionary<int, IVBucket>();
var vBucketForwardMap = _vBucketServerMap.VBucketMapForward;
var vBucketMap = _vBucketServerMap.VBucketMap;

Log.Info(m => m("Creating VBuckets {0} and FMaps {1} for Rev#{2}", vBucketMap.Length,
vBucketForwardMap == null ? 0: vBucketForwardMap.Length, Rev));

Expand Down
6 changes: 1 addition & 5 deletions Src/Couchbase/Core/IKeyMapper.cs
@@ -1,13 +1,9 @@
using System.Security.Cryptography;

namespace Couchbase.Core
namespace Couchbase.Core
{
internal interface IKeyMapper
{
IMappedNode MapKey(string key);

HashAlgorithm HashAlgorithm { get; set; }

int Rev { get; set; }
}
}
Expand Down

0 comments on commit 28af3d9

Please sign in to comment.