This is an automated email from the ASF dual-hosted git repository. bertty pushed a commit to branch debugger in repository https://gitbox.apache.org/repos/asf/incubator-wayang.git
commit 2209aa7d22c0c3024fdddc97e53a1e6963940d1e Author: Bertty Contreras-Rojas <[email protected]> AuthorDate: Mon Apr 5 23:27:49 2021 -0400 [WAYANG-28] hackit unique identifier generators --- .../plugin/hackit/core/identifiers/HackitID.java | 21 +++++ .../hackit/core/identifiers/HackitIDGenerator.java | 80 ++++++++++++++++++ .../generator/DistributeSequencial.java | 32 ++++++++ .../identifiers/generator/TwitterSnowflake.java | 95 ++++++++++++++++++++++ 4 files changed, 228 insertions(+) diff --git a/wayang-plugins/wayang-hackit/wayang-hackit-core/src/main/java/org/apache/wayang/plugin/hackit/core/identifiers/HackitID.java b/wayang-plugins/wayang-hackit/wayang-hackit-core/src/main/java/org/apache/wayang/plugin/hackit/core/identifiers/HackitID.java new file mode 100644 index 0000000..1b55679 --- /dev/null +++ b/wayang-plugins/wayang-hackit/wayang-hackit-core/src/main/java/org/apache/wayang/plugin/hackit/core/identifiers/HackitID.java @@ -0,0 +1,21 @@ +/* + * 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.wayang.plugin.hackit.core.identifiers; + +public class HackitID { +} diff --git a/wayang-plugins/wayang-hackit/wayang-hackit-core/src/main/java/org/apache/wayang/plugin/hackit/core/identifiers/HackitIDGenerator.java b/wayang-plugins/wayang-hackit/wayang-hackit-core/src/main/java/org/apache/wayang/plugin/hackit/core/identifiers/HackitIDGenerator.java new file mode 100644 index 0000000..ad34332 --- /dev/null +++ b/wayang-plugins/wayang-hackit/wayang-hackit-core/src/main/java/org/apache/wayang/plugin/hackit/core/identifiers/HackitIDGenerator.java @@ -0,0 +1,80 @@ +/* + * 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.wayang.plugin.hackit.core.identifiers; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.security.SecureRandom; +import java.util.Enumeration; + +/** + * Generate the next ID, N depends of the type that is need + * */ +public abstract class HackitIDGenerator<N, O> { + + private boolean is_address_calculated = false; + protected InetAddress address_host; + + /** This is the identifier of the process, task, or machine, depends of the platform + * but is use for the generators. + * */ + protected N identify_process; + + public HackitIDGenerator(){ + this.identify_process = null; + this.address_host = null; + } + + public HackitIDGenerator(N identify_process) { + this.identify_process = identify_process; + getAddress(); + } + + protected void getAddress(){ + if( ! this.is_address_calculated ){ + try { + this.address_host = InetAddress.getLocalHost(); + } catch (Exception e) { + this.address_host = null; + } + } + } + + protected static int createNodeId() { + int nodeId; + try { + StringBuilder sb = new StringBuilder(); + Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); + while (networkInterfaces.hasMoreElements()) { + NetworkInterface networkInterface = networkInterfaces.nextElement(); + byte[] mac = networkInterface.getHardwareAddress(); + if (mac != null) { + for(int i = 0; i < mac.length; i++) { + sb.append(String.format("%02X", mac[i])); + } + } + } + nodeId = sb.toString().hashCode(); + } catch (Exception ex) { + nodeId = (new SecureRandom().nextInt()); + } + return nodeId; + } + + public abstract O generateId(); +} diff --git a/wayang-plugins/wayang-hackit/wayang-hackit-core/src/main/java/org/apache/wayang/plugin/hackit/core/identifiers/generator/DistributeSequencial.java b/wayang-plugins/wayang-hackit/wayang-hackit-core/src/main/java/org/apache/wayang/plugin/hackit/core/identifiers/generator/DistributeSequencial.java new file mode 100644 index 0000000..f146d65 --- /dev/null +++ b/wayang-plugins/wayang-hackit/wayang-hackit-core/src/main/java/org/apache/wayang/plugin/hackit/core/identifiers/generator/DistributeSequencial.java @@ -0,0 +1,32 @@ +/* + * 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.wayang.plugin.hackit.core.identifiers.generator; + +import org.apache.wayang.plugin.hackit.core.identifiers.HackitIDGenerator; + +public class DistributeSequencial extends HackitIDGenerator<Integer, Long> { + + long current = 0; + + @Override + public Long generateId() { + Long tmp = current; + current++; + return tmp; + } +} diff --git a/wayang-plugins/wayang-hackit/wayang-hackit-core/src/main/java/org/apache/wayang/plugin/hackit/core/identifiers/generator/TwitterSnowflake.java b/wayang-plugins/wayang-hackit/wayang-hackit-core/src/main/java/org/apache/wayang/plugin/hackit/core/identifiers/generator/TwitterSnowflake.java new file mode 100644 index 0000000..05d0998 --- /dev/null +++ b/wayang-plugins/wayang-hackit/wayang-hackit-core/src/main/java/org/apache/wayang/plugin/hackit/core/identifiers/generator/TwitterSnowflake.java @@ -0,0 +1,95 @@ +/* + * 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.wayang.plugin.hackit.core.identifiers.generator; + +import org.apache.wayang.plugin.hackit.core.identifiers.HackitIDGenerator; + +import java.time.Instant; + +public class TwitterSnowflake extends HackitIDGenerator<Integer, Long> { + private static final int TOTAL_BITS = 64; + private static final int EPOCH_BITS = 42; + private static final int NODE_ID_BITS = 10; + private static final int SEQUENCE_BITS = 12; + + private static final int maxNodeId = (int)(Math.pow(2, NODE_ID_BITS) - 1); + private static final int maxSequence = (int)(Math.pow(2, SEQUENCE_BITS) - 1); + + // Custom Epoch (January 1, 2015 Midnight UTC = 2015-01-01T00:00:00Z) + private static final long CUSTOM_EPOCH = 1420070400000L; + + private volatile long lastTimestamp = -1L; + private volatile long sequence = 0L; + + // Create SequenceGenerator with a nodeId + public TwitterSnowflake(int nodeId) { + if(nodeId < 0 || nodeId > maxNodeId) { + throw new IllegalArgumentException(String.format("NodeId must be between %d and %d", 0, maxNodeId)); + } + this.identify_process = nodeId; + } + + // Let SequenceGenerator generate a nodeId + public TwitterSnowflake() { + this( createNodeId() & maxNodeId); + } + + @Override + public Long generateId() { + return this.nextId(); + } + + public synchronized long nextId() { + long currentTimestamp = timestamp(); + + if(currentTimestamp < lastTimestamp) { + throw new IllegalStateException("Invalid System Clock!"); + } + + if (currentTimestamp == lastTimestamp) { + sequence = (sequence + 1) & maxSequence; + if(sequence == 0) { + // Sequence Exhausted, wait till next millisecond. + currentTimestamp = waitNextMillis(currentTimestamp); + } + } else { + // reset sequence to start with zero for the next millisecond + sequence = 0; + } + + lastTimestamp = currentTimestamp; + + long id = currentTimestamp << (TOTAL_BITS - EPOCH_BITS); + id |= (this.identify_process << (TOTAL_BITS - EPOCH_BITS - NODE_ID_BITS)); + id |= sequence; + return id; + } + + // Get current timestamp in milliseconds, adjust for the custom epoch. + private static long timestamp() { + return Instant.now().toEpochMilli() - CUSTOM_EPOCH; + } + + // Block and wait till next millisecond + private long waitNextMillis(long currentTimestamp) { + while (currentTimestamp == lastTimestamp) { + currentTimestamp = timestamp(); + } + return currentTimestamp; + } +}
