INT-1188, Added support for MAC address discovery to ensure Global uniqueness of UUID

This commit is contained in:
Oleg Zhurakousky
2010-06-18 16:30:10 +00:00
parent 75d2add40c
commit 6c320719e1
3 changed files with 91 additions and 3 deletions

View File

@@ -77,7 +77,8 @@ public final class MessageHeaders implements Map<String, Object>, Serializable {
public MessageHeaders(Map<String, Object> headers) {
this.headers = (headers != null) ? new HashMap<String, Object>(headers) : new HashMap<String, Object>();
this.headers.put(ID, TimeBasedUUIDGenerator.generateId());
//this.headers.put(ID, TimeBasedUUIDGenerator.generateId());
this.headers.put(ID, UUID.randomUUID());
this.headers.put(TIMESTAMP, new Long(System.currentTimeMillis()));
if (this.headers.get(HISTORY) == null) {
this.headers.put(HISTORY, new MessageHistory());

View File

@@ -15,8 +15,13 @@
*/
package org.springframework.integration.core;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.UUID;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Will generate time-based UUID (version 1 UUID).
* This will allow Message ID to be unique but also contain an
@@ -28,6 +33,27 @@ import java.util.UUID;
class TimeBasedUUIDGenerator {
public static final Object lock = new Object();
private static long lastTime;
private static final Log logger = LogFactory.getLog(TimeBasedUUIDGenerator.class);
private static long macAddressAsLong = 0;
static {
try {
InetAddress address = InetAddress.getLocalHost();
NetworkInterface ni = NetworkInterface.getByInetAddress(address);
if (ni != null) {
byte[] mac = ni.getHardwareAddress();
//Converts array of unsigned bytes to an long
if (mac != null) {
for (int i = 0; i < mac.length; i++) {
macAddressAsLong |= mac[i] & 0xFF;
macAddressAsLong <<= 8;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Will generate unique time based UUID where the next UUID is
@@ -45,6 +71,7 @@ class TimeBasedUUIDGenerator {
*/
public final static UUID generateIdFromTimestamp(long currentTimeMillis){
long time;
long macNanoTime;
synchronized (lock) {
if (currentTimeMillis > lastTime) {
lastTime = currentTimeMillis;
@@ -63,7 +90,17 @@ class TimeBasedUUIDGenerator {
// hi Time
time |= 0x1000 | ((currentTimeMillis >> 48) & 0x0FFF); // version 1
return new UUID(time, System.nanoTime());
macNanoTime = macAddressAsLong;
if (macNanoTime == 0){
logger.warn("Can not determine machine's MAC address. Will use System.nanoTime() for UUID generation, however there is a slim chance of it not being globally unique");
macNanoTime = System.nanoTime();
} else {
//considering the type of time returned by nanoTime, this will ensure that
// even if more then one process is running on the same machine, the id is still unique
macNanoTime |= System.nanoTime() & 0xFF;
macNanoTime <<= 8;
}
return new UUID(time, macNanoTime);
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2002-2010 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.core;
import java.util.UUID;
import org.junit.Assert;
import org.junit.Test;
/**
* @author Oleg Zhurakousky
*
*/
public class TimeBasedUUIDGeneratorTests {
@Test
public void testGreaterThen(){
UUID id = TimeBasedUUIDGenerator.generateId();
for (int i = 0; i < 1000; i++) {
UUID newId = TimeBasedUUIDGenerator.generateId();
// tests, that newly created UUID is always greater then the previous one.
Assert.assertTrue(newId.compareTo(id) == 1);
id = newId;
}
}
@Test
public void testUniqueness(){
long timestamp = System.currentTimeMillis();
UUID id = TimeBasedUUIDGenerator.generateIdFromTimestamp(timestamp);
for (int i = 0; i < 1000; i++) {
UUID newId = TimeBasedUUIDGenerator.generateIdFromTimestamp(timestamp);
// tests, that newly created UUID is always greater then the previous one.
Assert.assertTrue(newId.compareTo(id) == 1);
id = newId;
}
}
}