You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wayang.apache.org by be...@apache.org on 2021/04/06 04:13:55 UTC
[incubator-wayang] 04/12: [WAYANG-28] hackit unique identifier
generators
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 <be...@scalytics.io>
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;
+ }
+}