You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2017/06/09 10:44:09 UTC

camel git commit: CAMEL-11338: New DefaultUuidGenerator to startup Camel faster

Repository: camel
Updated Branches:
  refs/heads/master cce160b48 -> 89339ede1


CAMEL-11338: New DefaultUuidGenerator to startup Camel faster


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/89339ede
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/89339ede
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/89339ede

Branch: refs/heads/master
Commit: 89339ede11e22b7a6a21400a5c59e1c361f5c94e
Parents: cce160b
Author: Claus Ibsen <da...@apache.org>
Authored: Fri Jun 9 11:53:06 2017 +0200
Committer: Claus Ibsen <da...@apache.org>
Committed: Fri Jun 9 12:44:01 2017 +0200

----------------------------------------------------------------------
 .../camel/impl/ActiveMQUuidGenerator.java       |   4 +
 .../apache/camel/impl/DefaultCamelContext.java  |   2 +-
 .../apache/camel/impl/DefaultUuidGenerator.java | 156 +++++++++++++++++++
 .../apache/camel/impl/SimpleUuidGenerator.java  |   3 +-
 .../camel/impl/DefaultCamelContextTest.java     |   2 +-
 .../camel/impl/DefaultUuidGeneratorTest.java    |  57 +++++++
 .../spring/CamelContextFactoryBeanTest.java     |   4 +-
 7 files changed, 223 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/89339ede/camel-core/src/main/java/org/apache/camel/impl/ActiveMQUuidGenerator.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/ActiveMQUuidGenerator.java b/camel-core/src/main/java/org/apache/camel/impl/ActiveMQUuidGenerator.java
index 7a4f0d0..84202a0 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/ActiveMQUuidGenerator.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/ActiveMQUuidGenerator.java
@@ -35,7 +35,10 @@ import org.slf4j.LoggerFactory;
  * <p/>
  * The JVM system property {@link #PROPERTY_IDGENERATOR_PORT} can be used to set a specific port
  * number to be used as part of the initialization process to generate unique UUID.
+ *
+ * @deprecated replaced by {@link DefaultUuidGenerator}
  */
+@Deprecated
 public class ActiveMQUuidGenerator implements UuidGenerator {
 
     // use same JVM property name as ActiveMQ
@@ -48,6 +51,7 @@ public class ActiveMQUuidGenerator implements UuidGenerator {
     private static int instanceCount;
     private static String hostName;
     private String seed;
+    // must use AtomicLong to ensure atomic get and update operation that is thread-safe
     private final AtomicLong sequence = new AtomicLong(1);
     private final int length;
 

http://git-wip-us.apache.org/repos/asf/camel/blob/89339ede/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
index 136c063..44419e4 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultCamelContext.java
@@ -4553,7 +4553,7 @@ public class DefaultCamelContext extends ServiceSupport implements ModelCamelCon
             // either "Production" or "Development"
             return new JavaUuidGenerator();
         } else {
-            return new ActiveMQUuidGenerator();
+            return new DefaultUuidGenerator();
         }
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/89339ede/camel-core/src/main/java/org/apache/camel/impl/DefaultUuidGenerator.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/DefaultUuidGenerator.java b/camel-core/src/main/java/org/apache/camel/impl/DefaultUuidGenerator.java
new file mode 100644
index 0000000..080520a
--- /dev/null
+++ b/camel-core/src/main/java/org/apache/camel/impl/DefaultUuidGenerator.java
@@ -0,0 +1,156 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.impl;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.camel.spi.UuidGenerator;
+import org.apache.camel.util.InetAddressUtil;
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Default {@link UuidGenerator} that is based on the {@link ActiveMQUuidGenerator} but
+ * is optimized for Camel usage to startup faster and avoid use local network binding to obtain a random number.
+ */
+public class DefaultUuidGenerator implements UuidGenerator {
+
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultUuidGenerator.class);
+    private static final String UNIQUE_STUB;
+    private static int instanceCount;
+    private static String hostName;
+    private String seed;
+    // must use AtomicLong to ensure atomic get and update operation that is thread-safe
+    private final AtomicLong sequence = new AtomicLong(1);
+    private final int length;
+
+    static {
+        String stub = "";
+        boolean canAccessSystemProps = true;
+        try {
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null) {
+                sm.checkPropertiesAccess();
+            }
+        } catch (SecurityException se) {
+            canAccessSystemProps = false;
+        }
+
+        if (canAccessSystemProps) {
+
+            try {
+                if (hostName == null) {
+                    hostName = InetAddressUtil.getLocalHostName();
+                }
+                stub = "-" + System.currentTimeMillis() + "-";
+            } catch (Exception e) {
+                if (LOG.isTraceEnabled()) {
+                    LOG.trace("Cannot generate unique stub by using DNS", e);
+                } else {
+                    LOG.warn("Cannot generate unique stub by using DNS due " + e.getMessage() + ". This exception is ignored.");
+                }
+            }
+        }
+
+        // fallback to use localhost
+        if (hostName == null) {
+            hostName = "localhost";
+        }
+        hostName = sanitizeHostName(hostName);
+
+        if (ObjectHelper.isEmpty(stub)) {
+            stub = "-1-" + System.currentTimeMillis() + "-";
+        }
+        UNIQUE_STUB = stub;
+    }
+
+    public DefaultUuidGenerator(String prefix) {
+        synchronized (UNIQUE_STUB) {
+            this.seed = prefix + UNIQUE_STUB + (instanceCount++) + "-";
+            // let the ID be friendly for URL and file systems
+            this.seed = generateSanitizedId(this.seed);
+            this.length = seed.length() + ("" + Long.MAX_VALUE).length();
+        }
+    }
+
+    public DefaultUuidGenerator() {
+        this("ID-" + hostName);
+    }
+
+    /**
+     * As we have to find the hostname as a side-affect of generating a unique
+     * stub, we allow it's easy retrieval here
+     * 
+     * @return the local host name
+     */
+    public static String getHostName() {
+        return hostName;
+    }
+
+    public static String sanitizeHostName(String hostName) {
+        boolean changed = false;
+
+        StringBuilder sb = new StringBuilder();
+        for (char ch : hostName.toCharArray()) {
+            // only include ASCII chars
+            if (ch < 127) {
+                sb.append(ch);
+            } else {
+                changed = true;
+            }
+        }
+
+        if (changed) {
+            String newHost = sb.toString();
+            LOG.info("Sanitized hostname from: {} to: {}", hostName, newHost);
+            return newHost;
+        } else {
+            return hostName;
+        }
+    }
+
+    public String generateUuid() {
+        StringBuilder sb = new StringBuilder(length);
+        sb.append(seed);
+        sb.append(sequence.getAndIncrement());
+        return sb.toString();
+    }
+
+    /**
+     * Generate a unique ID - that is friendly for a URL or file system
+     * 
+     * @return a unique id
+     */
+    public String generateSanitizedId() {
+        return generateSanitizedId(generateUuid());
+    }
+
+    /**
+     * Ensures that the id is friendly for a URL or file system
+     *
+     * @param id the unique id
+     * @return the id as file friendly id
+     */
+    public static String generateSanitizedId(String id) {
+        id = id.replace(':', '-');
+        id = id.replace('_', '-');
+        id = id.replace('.', '-');
+        id = id.replace('/', '-');
+        return id;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/89339ede/camel-core/src/main/java/org/apache/camel/impl/SimpleUuidGenerator.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/impl/SimpleUuidGenerator.java b/camel-core/src/main/java/org/apache/camel/impl/SimpleUuidGenerator.java
index b2738f8..e08371a 100644
--- a/camel-core/src/main/java/org/apache/camel/impl/SimpleUuidGenerator.java
+++ b/camel-core/src/main/java/org/apache/camel/impl/SimpleUuidGenerator.java
@@ -21,7 +21,8 @@ import java.util.concurrent.atomic.AtomicLong;
 import org.apache.camel.spi.UuidGenerator;
 
 /**
- * This implementation uses a counter which increments by one
+ * This implementation uses a counter which increments by one.
+ * This generator is not unique per host or JVM, as its private per CamelContext.
  */
 public class SimpleUuidGenerator implements UuidGenerator {
     

http://git-wip-us.apache.org/repos/asf/camel/blob/89339ede/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextTest.java b/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextTest.java
index 4a8e84b..2487a52 100644
--- a/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextTest.java
+++ b/camel-core/src/test/java/org/apache/camel/impl/DefaultCamelContextTest.java
@@ -83,7 +83,7 @@ public class DefaultCamelContextTest extends TestSupport {
         ctx.disableJMX();
         UuidGenerator uuidGenerator = ctx.getUuidGenerator();
         assertNotNull(uuidGenerator);
-        assertEquals(uuidGenerator.getClass(), ActiveMQUuidGenerator.class);
+        assertEquals(uuidGenerator.getClass(), DefaultUuidGenerator.class);
     }
 
     public void testGetComponents() throws Exception {

http://git-wip-us.apache.org/repos/asf/camel/blob/89339ede/camel-core/src/test/java/org/apache/camel/impl/DefaultUuidGeneratorTest.java
----------------------------------------------------------------------
diff --git a/camel-core/src/test/java/org/apache/camel/impl/DefaultUuidGeneratorTest.java b/camel-core/src/test/java/org/apache/camel/impl/DefaultUuidGeneratorTest.java
new file mode 100644
index 0000000..510a437
--- /dev/null
+++ b/camel-core/src/test/java/org/apache/camel/impl/DefaultUuidGeneratorTest.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.camel.impl;
+
+import junit.framework.TestCase;
+import org.apache.camel.util.StopWatch;
+import org.apache.camel.util.TimeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DefaultUuidGeneratorTest extends TestCase {
+    
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultUuidGeneratorTest.class);
+
+    public void testGenerateUUID() {
+        DefaultUuidGenerator uuidGenerator = new DefaultUuidGenerator();
+
+        String firstUUID = uuidGenerator.generateUuid();
+        String secondUUID = uuidGenerator.generateUuid();
+
+        assertNotSame(firstUUID, secondUUID);
+    }
+
+    public void testPerformance() {
+        DefaultUuidGenerator uuidGenerator = new DefaultUuidGenerator();
+        StopWatch watch = new StopWatch();
+
+        LOG.info("First id: " + uuidGenerator.generateUuid());
+        for (int i = 0; i < 500000; i++) {
+            uuidGenerator.generateUuid();
+        }
+        LOG.info("Last id:  " + uuidGenerator.generateUuid());
+
+        LOG.info("Took " + TimeUtils.printDuration(watch.taken()));
+    }
+
+    public void testSanitizeHostName() throws Exception {
+        assertEquals("somehost.lan", DefaultUuidGenerator.sanitizeHostName("somehost.lan"));
+        // include a UTF-8 char in the text \u0E08 is a Thai elephant
+        assertEquals("otherhost.lan", DefaultUuidGenerator.sanitizeHostName("other\u0E08host.lan"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/89339ede/components/camel-spring/src/test/java/org/apache/camel/spring/CamelContextFactoryBeanTest.java
----------------------------------------------------------------------
diff --git a/components/camel-spring/src/test/java/org/apache/camel/spring/CamelContextFactoryBeanTest.java b/components/camel-spring/src/test/java/org/apache/camel/spring/CamelContextFactoryBeanTest.java
index 4fd8721..5b300aa 100644
--- a/components/camel-spring/src/test/java/org/apache/camel/spring/CamelContextFactoryBeanTest.java
+++ b/components/camel-spring/src/test/java/org/apache/camel/spring/CamelContextFactoryBeanTest.java
@@ -25,8 +25,8 @@ import java.util.List;
 import javax.xml.bind.JAXBContext;
 
 import junit.framework.TestCase;
-import org.apache.camel.impl.ActiveMQUuidGenerator;
 import org.apache.camel.impl.DefaultModelJAXBContextFactory;
+import org.apache.camel.impl.DefaultUuidGenerator;
 import org.apache.camel.impl.SimpleUuidGenerator;
 import org.apache.camel.spi.ModelJAXBContextFactory;
 import org.apache.camel.spi.UuidGenerator;
@@ -55,7 +55,7 @@ public class CamelContextFactoryBeanTest extends TestCase {
         
         UuidGenerator uuidGenerator = factory.getContext().getUuidGenerator();
         
-        assertTrue(uuidGenerator instanceof ActiveMQUuidGenerator);
+        assertTrue(uuidGenerator instanceof DefaultUuidGenerator);
     }
     
     public void testGetCustomUuidGenerator() throws Exception {