Skip to content

Implement global position #169

@johanhaleby

Description

@johanhaleby

Use snowflake-id and generate the id like this:

import java.net.NetworkInterface;
import java.security.MessageDigest;
import java.util.Enumeration;
import java.util.Random;

public class NodeIdGenerator {

    private static final int MAX_NODE_ID = 1024; // 10-bit node ID space

    /**
     * Generate a unique node ID by combining current time in millis and a unique machine fingerprint.
     * Falls back to random salt if MAC address is unavailable.
     */
    public static int generateNodeId() {
        long epochMillis = System.currentTimeMillis();
        String machineFingerprint = getMachineFingerprint();
        if (machineFingerprint == null) {
            machineFingerprint = generateRandomSalt();
        }

        // Combine epochMillis and machine fingerprint to generate a unique ID
        String uniqueString = epochMillis + "-" + machineFingerprint;
        return hashToInt(uniqueString, MAX_NODE_ID);
    }

    /**
     * Get the MAC address as a unique identifier.
     */
    private static String getMachineFingerprint() {
        try {
            Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
            while (networkInterfaces.hasMoreElements()) {
                NetworkInterface network = networkInterfaces.nextElement();
                byte[] mac = network.getHardwareAddress();

                if (mac != null) {
                    StringBuilder macAddress = new StringBuilder();
                    for (byte b : mac) {
                        macAddress.append(String.format("%02X", b));
                    }
                    return macAddress.toString();
                }
            }
        } catch (Exception e) {
            // Fallback if MAC address cannot be determined
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Generate a random salt for cases where MAC address is unavailable.
     */
    private static String generateRandomSalt() {
        Random random = new Random();
        byte[] salt = new byte[6]; // Generate 6 random bytes
        random.nextBytes(salt);

        StringBuilder saltString = new StringBuilder();
        for (byte b : salt) {
            saltString.append(String.format("%02X", b));
        }
        return saltString.toString();
    }

    /**
     * Hash the input string to an integer and constrain it to the max value.
     */
    private static int hashToInt(String input, int maxValue) {
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-256");
            byte[] hash = digest.digest(input.getBytes());

            // Use the first 4 bytes of the hash to compute an integer
            int result = 0;
            for (int i = 0; i < 4; i++) {
                result = (result << 8) | (hash[i] & 0xFF);
            }
            return Math.abs(result) % maxValue;
        } catch (Exception e) {
            throw new RuntimeException("Error hashing input string", e);
        }
    }

    public static void main(String[] args) {
        int nodeId = generateNodeId();
        System.out.println("Generated Node ID: " + nodeId);
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions