From 413e446c07c99a7a1f44592df90f23a757df96bf Mon Sep 17 00:00:00 2001 From: Vo Duc Phuong Date: Mon, 13 Nov 2017 16:14:54 +0700 Subject: [PATCH] Implement the MAC address guessing service - Retrieve all current network interfaces, remove virtual and loopback address, then pick the first one - Fix some bracket () so intellij will shutup --- .../snowflake4s/MachineIdentifier.scala | 4 +-- .../snowflake4s/algorithms/Snowflake.scala | 4 +-- .../identifier/MachineMACAddress.scala | 33 +++++++++++++++---- .../snowflake4s/identifier/MaskConfig.scala | 4 +-- 4 files changed, 32 insertions(+), 13 deletions(-) diff --git a/src/main/scala/com/septech/snowflake4s/MachineIdentifier.scala b/src/main/scala/com/septech/snowflake4s/MachineIdentifier.scala index f1d6cb5..90ef545 100644 --- a/src/main/scala/com/septech/snowflake4s/MachineIdentifier.scala +++ b/src/main/scala/com/septech/snowflake4s/MachineIdentifier.scala @@ -17,8 +17,8 @@ package com.septech.snowflake4s trait MachineIdentifier { - def getId(): String + def getId: String - def getWorkerId(): String + def getWorkerId: String } diff --git a/src/main/scala/com/septech/snowflake4s/algorithms/Snowflake.scala b/src/main/scala/com/septech/snowflake4s/algorithms/Snowflake.scala index 221d4ec..5a7f84a 100644 --- a/src/main/scala/com/septech/snowflake4s/algorithms/Snowflake.scala +++ b/src/main/scala/com/septech/snowflake4s/algorithms/Snowflake.scala @@ -61,8 +61,8 @@ private[snowflake4s] class Snowflake @Inject()(identifier: MachineIdentifier) ex final private val sequenceMask: Long = -1L ^ (-1L << sequenceBits) final private var lastTimestamp: Long = -1L - final private val MACHINE_ID: Long = identifier.getId().toLong - final private val WORKER_ID: Long = identifier.getWorkerId().toLong + final private val MACHINE_ID: Long = identifier.getId.toLong + final private val WORKER_ID: Long = identifier.getWorkerId.toLong override def generate(): String = bulkGenerate(1).headOption.fold[String](throw new GenerateException)(id => id) diff --git a/src/main/scala/com/septech/snowflake4s/identifier/MachineMACAddress.scala b/src/main/scala/com/septech/snowflake4s/identifier/MachineMACAddress.scala index 9ea7d9c..7ff717f 100644 --- a/src/main/scala/com/septech/snowflake4s/identifier/MachineMACAddress.scala +++ b/src/main/scala/com/septech/snowflake4s/identifier/MachineMACAddress.scala @@ -27,21 +27,40 @@ import scala.util.Try private[snowflake4s] class MachineMACAddress extends MachineIdentifier { - override def getId(): String = Try { - val localNetworkInterface = NetworkInterface.getByInetAddress(InetAddress.getLocalHost) + override def getId: String = Try { + val localNetworkInterface = MachineMACAddress.guessBestInterface - localNetworkInterface - .getHardwareAddress.toList - .map(byte => Integer.parseInt(String.format("%02x", byte.asInstanceOf[Object]), 16)) - .foldLeft(0L) { case (acc, item) => acc * 256 + item } + localNetworkInterface.get // NPE here + .getHardwareAddress + .map(byte => byte & 0xFF) + .foldLeft(0L) { (acc, item) => (acc << 8) + item } .toString } match { case Failure(_) => throw new MacAddressException() case Success(address) => address } - override def getWorkerId() = { + override def getWorkerId: String = { ManagementFactory.getRuntimeMXBean.getName.split("@").headOption .fold(throw new RuntimeException("Can not get process id of application"))(pid => pid) } } + +private object MachineMACAddress { + import scala.collection.JavaConverters._ + + def getAvailableInterfaces: Map[String, NetworkInterface] = + NetworkInterface.getNetworkInterfaces.asScala + .foldLeft(Map.empty[String, NetworkInterface]){ (map, intf) => + if (isValidInterface(intf)) + map + ((intf.getName, intf)) + else + map + } + + def guessBestInterface: Option[NetworkInterface] = + getAvailableInterfaces.headOption.map(_._2) + + private def isValidInterface(intf: NetworkInterface): Boolean = + Option(intf.getHardwareAddress).isDefined && intf.isUp && !intf.isVirtual +} \ No newline at end of file diff --git a/src/main/scala/com/septech/snowflake4s/identifier/MaskConfig.scala b/src/main/scala/com/septech/snowflake4s/identifier/MaskConfig.scala index 580fe90..40fc34a 100644 --- a/src/main/scala/com/septech/snowflake4s/identifier/MaskConfig.scala +++ b/src/main/scala/com/septech/snowflake4s/identifier/MaskConfig.scala @@ -6,11 +6,11 @@ private[snowflake4s] class MaskConfig extends MachineIdentifier { private val defaultMachineId: Long = 1L private val defaultWorkerId: Long = 1L - override def getId(): String = { + override def getId: String = { Option(System.getProperty("snowflake4s.twitter.machine_id")).getOrElse(defaultMachineId.toString) } - def getWorkerId(): String = { + def getWorkerId: String = { Option(System.getProperty("snowflake4s.twitter.worker_id")).getOrElse(defaultWorkerId.toString) }