Skip to content

Commit 9ba1fc5

Browse files
committed
Implemented 3 GeneratorIdCreators
These generatorId creators (better names are welcome) should make it easier to 'determine' a generator-id. See #65 for more info.
1 parent e084d23 commit 9ba1fc5

7 files changed

+181
-1
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using System;
2+
3+
namespace IdGen;
4+
5+
public static class DatacenterMachineIdGeneratorIdCreator
6+
{
7+
public static int Create(int datacenterid, int workerid, byte datacenterbits, byte workerbits)
8+
=> datacenterbits + workerbits > 31
9+
? throw new InvalidOperationException("The total number of datacenter and worker bits should not exceed 31")
10+
: datacenterid < 0 || datacenterid >= (1 << datacenterbits)
11+
? throw new ArgumentOutOfRangeException(nameof(datacenterid), $"Datacenter Id should be between 0 and {(1 << datacenterbits) - 1}")
12+
: workerid < 0 || workerid >= (1 << workerbits)
13+
? throw new ArgumentOutOfRangeException(nameof(workerid), $"Worker Id should be between 0 and {(1 << workerbits) - 1}")
14+
: (datacenterid << workerbits) | workerid;
15+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#if NETSTANDARD2_0_OR_GREATER
2+
3+
using System;
4+
using System.Linq;
5+
using System.Net;
6+
using System.Net.Sockets;
7+
8+
namespace IdGen;
9+
10+
public enum IpAddressType
11+
{
12+
IPv4 = 4,
13+
IPv6 = 6,
14+
IPvAny = 0
15+
}
16+
17+
public static class IPAddressGeneratorIdCreator
18+
{
19+
public static int Create(IpAddressType ipType, byte generatorIdBits)
20+
=> Create(GetLocalIp(ipType), generatorIdBits);
21+
22+
public static int Create(IpAddressType ipType, IdStructure idStructure)
23+
=> Create(GetLocalIp(ipType), idStructure.GeneratorIdBits);
24+
25+
public static int Create(IPAddress ip, IdStructure idStructure)
26+
=> Create(ip, idStructure.GeneratorIdBits);
27+
28+
public static int Create(IPAddress ip, byte generatorIdBits)
29+
{
30+
if (generatorIdBits is < 0 or > 31)
31+
{
32+
throw new ArgumentOutOfRangeException(nameof(generatorIdBits), Translations.ERR_GENERATORID_CANNOT_EXCEED_31BITS);
33+
}
34+
35+
var ipbytes = ip.GetAddressBytes().Reverse().ToArray();
36+
return BitConverter.ToInt32(ipbytes, 0) & ((1 << generatorIdBits) - 1) & 0x7FFFFFFF;
37+
}
38+
39+
public static IPAddress GetLocalIp(IpAddressType ipAddressType)
40+
=> Dns.GetHostEntry(Dns.GetHostName()).AddressList.FirstOrDefault(i => ipAddressType == IpAddressType.IPvAny || i.AddressFamily == (ipAddressType == IpAddressType.IPv4 ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6))
41+
?? throw new InvalidOperationException("Unable to determine IP address");
42+
}
43+
#endif

IdGen/IdGen.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
</ItemGroup>
4040

4141
<ItemGroup>
42-
<PackageReference Include="PolySharp" Version="1.14.1">
42+
<PackageReference Include="PolySharp" Version="1.15.0">
4343
<PrivateAssets>all</PrivateAssets>
4444
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
4545
</PackageReference>
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#if NETSTANDARD2_0_OR_GREATER
2+
3+
using System;
4+
using System.Linq;
5+
using System.Net.NetworkInformation;
6+
7+
namespace IdGen;
8+
9+
public static class MacAddressGeneratorIdCreator
10+
{
11+
public static int Create(byte generatorIdBits)
12+
{
13+
var nic = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault()
14+
?? throw new InvalidOperationException("Unable to determine MAC address");
15+
16+
return Create(nic.GetPhysicalAddress().GetAddressBytes().Reverse().ToArray(), generatorIdBits);
17+
}
18+
19+
public static int Create(byte[] macAddress, byte generatorIdBits)
20+
=> generatorIdBits is < 0 or > 31
21+
? throw new ArgumentOutOfRangeException(nameof(generatorIdBits), Translations.ERR_GENERATORID_CANNOT_EXCEED_31BITS)
22+
: macAddress.Length != 6
23+
? throw new ArgumentException("MAC address must be 6 bytes long", nameof(macAddress))
24+
: BitConverter.ToInt32(macAddress, 0) & ((1 << generatorIdBits) - 1) & 0x7FFFFFFF;
25+
}
26+
#endif
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
using IdGen;
2+
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
using System;
4+
5+
namespace IdGenTests;
6+
7+
[TestClass]
8+
public class DatacenterMachineIdGeneratorIdCreatorTests
9+
10+
{
11+
[TestMethod]
12+
public void Create_ShouldCreateCorrectId()
13+
{
14+
Assert.AreEqual(0, DatacenterMachineIdGeneratorIdCreator.Create(0, 0, 4, 4));
15+
Assert.AreEqual(52394, DatacenterMachineIdGeneratorIdCreator.Create(204, 170, 8, 8));
16+
Assert.AreEqual(2147483647, DatacenterMachineIdGeneratorIdCreator.Create(536870911, 3, 29, 2));
17+
Assert.AreEqual(255, DatacenterMachineIdGeneratorIdCreator.Create(15, 15, 4, 4));
18+
Assert.AreEqual(255, DatacenterMachineIdGeneratorIdCreator.Create(127, 1, 7, 1));
19+
}
20+
21+
[TestMethod]
22+
[ExpectedException(typeof(InvalidOperationException))]
23+
public void Create_ShouldThrowOnMoreThan31TotalBits()
24+
=> DatacenterMachineIdGeneratorIdCreator.Create(0, 0, 30, 2);
25+
26+
[TestMethod]
27+
[ExpectedException(typeof(ArgumentOutOfRangeException))]
28+
public void Create_ShouldThrowOnDatacenterIdExceedingBits()
29+
=> DatacenterMachineIdGeneratorIdCreator.Create(4, 0, 2, 8);
30+
31+
[TestMethod]
32+
[ExpectedException(typeof(ArgumentOutOfRangeException))]
33+
public void Create_ShouldThrowOnWorkerIdExceedingBits()
34+
=> DatacenterMachineIdGeneratorIdCreator.Create(0, 4, 8, 2);
35+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
using IdGen;
2+
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
using System;
4+
using System.Net;
5+
6+
namespace IdGenTests;
7+
8+
[TestClass]
9+
public class IPAddressGeneratorIdCreatorTests
10+
{
11+
[TestMethod]
12+
public void Create_ShouldCreateCorrectId()
13+
{
14+
//IPv4
15+
Assert.AreEqual(1084783405, IPAddressGeneratorIdCreator.Create(IPAddress.Parse("192.168.123.45"), 31));
16+
Assert.AreEqual(13, IPAddressGeneratorIdCreator.Create(IPAddress.Parse("192.168.123.45"), 4));
17+
Assert.AreEqual(1, IPAddressGeneratorIdCreator.Create(IPAddress.Parse("192.168.0.1"), 16));
18+
19+
//IPv6
20+
Assert.AreEqual(1084783405, IPAddressGeneratorIdCreator.Create(IPAddress.Parse("::ffff:c0a8:7b2d"), 31));
21+
Assert.AreEqual(13, IPAddressGeneratorIdCreator.Create(IPAddress.Parse("::ffff:c0a8:7b2d"), 4));
22+
Assert.AreEqual(1, IPAddressGeneratorIdCreator.Create(IPAddress.Parse("::ffff:0:1"), 16));
23+
24+
IPAddressGeneratorIdCreator.Create(IpAddressType.IPvAny, 16);
25+
}
26+
27+
[TestMethod]
28+
public void Create_ShouldCreateCorrectIdForLocalIP() =>
29+
// This doesn't really test anything, but it's here to make sure GetLocalIp is invoked and doesn't throw
30+
Assert.AreNotEqual(0, IPAddressGeneratorIdCreator.Create(IpAddressType.IPvAny, 7));
31+
32+
[TestMethod]
33+
[ExpectedException(typeof(ArgumentOutOfRangeException))]
34+
public void Create_ShouldThrowOnMoreThan31Bits()
35+
=> IPAddressGeneratorIdCreator.Create(IPAddress.Parse("192.168.0.1"), 32);
36+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using IdGen;
2+
using Microsoft.VisualStudio.TestTools.UnitTesting;
3+
using System;
4+
5+
namespace IdGenTests;
6+
7+
[TestClass]
8+
public class MacAddressGeneratorIdCreatorTests
9+
{
10+
[TestMethod]
11+
public void Create_ShouldCreateCorrectId()
12+
// This doesn't really test anything, but it's here to make sure trying to gat a MacAddress doesn't throw
13+
=> Assert.AreNotEqual(0, MacAddressGeneratorIdCreator.Create(31));
14+
15+
[TestMethod]
16+
[ExpectedException(typeof(ArgumentOutOfRangeException))]
17+
public void Create_ShouldThrowOnMoreThan31Bits()
18+
=> MacAddressGeneratorIdCreator.Create(32);
19+
20+
21+
[TestMethod]
22+
[ExpectedException(typeof(ArgumentException))]
23+
public void Create_ShouldThrowOnIncorrectMacAddress()
24+
=> MacAddressGeneratorIdCreator.Create(new byte[3], 8);
25+
}

0 commit comments

Comments
 (0)