ASTERIXDB-1271: Revisit UUID Implementation
- Updated UUID implementation to eliminate marshalling to/from a pair
of longs, replacing with byte [].
- Eliminate all but one call to SecureRandom at init time, avoid risk
of entropy exhaustion
- Fix exceptions thrown
- Incorporate constant to represent number of bytes, String chars in
an instance of AUUID
- Split generated from parsed AUUID
- Eliminate intermediate StringBuilder construction on priting paths,
optimize imports
Change-Id: I9e90d42f6b62f80ad180dbd0c8c852db85b14173
Reviewed-on: https://asterix-gerrit.ics.uci.edu/610
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: abdullah alamoudi <bamousaa@gmail.com>
Reviewed-by: Till Westmann <tillw@apache.org>
diff --git a/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ADMDataParser.java b/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ADMDataParser.java
index 0fe2758..93aa18b 100644
--- a/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ADMDataParser.java
+++ b/asterix-external-data/src/main/java/org/apache/asterix/external/parser/ADMDataParser.java
@@ -55,7 +55,6 @@
import org.apache.asterix.om.util.container.IObjectPool;
import org.apache.asterix.om.util.container.ListObjectPool;
import org.apache.asterix.runtime.operators.file.adm.AdmLexer;
-import org.apache.asterix.runtime.operators.file.adm.AdmLexerException;
import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.apache.hyracks.data.std.api.IMutableValueStorage;
import org.apache.hyracks.data.std.util.ArrayBackedValueStorage;
@@ -296,7 +295,7 @@
// Dealing with UUID type that is represented by a string
final String tokenImage = admLexer.getLastTokenImage().substring(1,
admLexer.getLastTokenImage().length() - 1);
- aUUID.fromStringToAMuatbleUUID(tokenImage);
+ aUUID.parseUUIDString(tokenImage);
uuidSerde.serialize(aUUID, out);
} else {
throw new ParseException(mismatchErrorMessage + objectType.getTypeName());
@@ -1023,7 +1022,7 @@
APolygonSerializerDeserializer.parse(unquoted, out);
return true;
case UUID:
- aUUID.fromStringToAMuatbleUUID(unquoted);
+ aUUID.parseUUIDString(unquoted);
uuidSerde.serialize(aUUID, out);
return true;
default:
diff --git a/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractDataParser.java b/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractDataParser.java
index b10b9e9..cfd1b9c 100644
--- a/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractDataParser.java
+++ b/asterix-external-data/src/main/java/org/apache/asterix/external/parser/AbstractDataParser.java
@@ -92,7 +92,7 @@
protected AMutableString aString = new AMutableString("");
protected AMutableBinary aBinary = new AMutableBinary(null, 0, 0);
protected AMutableString aStringFieldName = new AMutableString("");
- protected AMutableUUID aUUID = new AMutableUUID(0, 0);
+ protected AMutableUUID aUUID = new AMutableUUID();
// For temporal and spatial data types
protected AMutableTime aTime = new AMutableTime(0);
protected AMutableDateTime aDateTime = new AMutableDateTime(0L);
@@ -145,7 +145,7 @@
// For UUID, we assume that the format is the string representation of UUID
// (xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxx) when parsing the data.
- // Thus, we need to call UUID.fromStringToAMuatbleUUID() to convert it to the internal representation (two long values).
+ // Thus, we need to call UUID.fromStringToAMutableUUID() to convert it to the internal representation (byte []).
@SuppressWarnings("unchecked")
protected ISerializerDeserializer<AUUID> uuidSerde = AqlSerializerDeserializerProvider.INSTANCE
.getSerializerDeserializer(BuiltinType.AUUID);
diff --git a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/adm/AUUIDPrinter.java b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/adm/AUUIDPrinter.java
index 86cb7ac..539b49c 100644
--- a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/adm/AUUIDPrinter.java
+++ b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/adm/AUUIDPrinter.java
@@ -24,7 +24,6 @@
import org.apache.asterix.om.base.AUUID;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.data.IPrinter;
-import org.apache.hyracks.data.std.primitive.LongPointable;
public class AUUIDPrinter implements IPrinter {
@@ -36,10 +35,10 @@
@Override
public void print(byte[] b, int s, int l, PrintStream ps) throws AlgebricksException {
- long msb = LongPointable.getLong(b, s + 1);
- long lsb = LongPointable.getLong(b, s + 9);
-
- ps.print("uuid(\"" + AUUID.toStringLiteralOnly(msb, lsb) + "\")");
+ StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 8);
+ buf.append("uuid(\"");
+ AUUID.appendLiteralOnly(b, s + 1, buf).append("\")");
+ ps.print(buf.toString());
}
}
diff --git a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AUUIDPrinter.java b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AUUIDPrinter.java
index 967131f..89f5e31 100644
--- a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AUUIDPrinter.java
+++ b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/csv/AUUIDPrinter.java
@@ -24,7 +24,6 @@
import org.apache.asterix.om.base.AUUID;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.data.IPrinter;
-import org.apache.hyracks.data.std.primitive.LongPointable;
public class AUUIDPrinter implements IPrinter {
@@ -36,10 +35,10 @@
@Override
public void print(byte[] b, int s, int l, PrintStream ps) throws AlgebricksException {
- long msb = LongPointable.getLong(b, s + 1);
- long lsb = LongPointable.getLong(b, s + 9);
-
- ps.print("\"" + AUUID.toStringLiteralOnly(msb, lsb) + "\"");
+ StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
+ buf.append('"');
+ AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
+ ps.print(buf.toString());
}
}
diff --git a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinter.java b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinter.java
index 20b87c2..2a59fe4 100644
--- a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinter.java
+++ b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/clean/AUUIDPrinter.java
@@ -24,7 +24,6 @@
import org.apache.asterix.om.base.AUUID;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.data.IPrinter;
-import org.apache.hyracks.data.std.primitive.LongPointable;
public class AUUIDPrinter implements IPrinter {
@@ -36,10 +35,10 @@
@Override
public void print(byte[] b, int s, int l, PrintStream ps) throws AlgebricksException {
- long msb = LongPointable.getLong(b, s + 1);
- long lsb = LongPointable.getLong(b, s + 9);
-
- ps.print("\"" + AUUID.toStringLiteralOnly(msb, lsb) + "\"");
+ StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
+ buf.append('"');
+ AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
+ ps.print(buf.toString());
}
}
diff --git a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/lossless/AUUIDPrinter.java b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/lossless/AUUIDPrinter.java
index f21cdff..c36de3a 100644
--- a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/lossless/AUUIDPrinter.java
+++ b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/printers/json/lossless/AUUIDPrinter.java
@@ -24,7 +24,6 @@
import org.apache.asterix.om.base.AUUID;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.data.IPrinter;
-import org.apache.hyracks.data.std.primitive.LongPointable;
public class AUUIDPrinter implements IPrinter {
@@ -36,10 +35,10 @@
@Override
public void print(byte[] b, int s, int l, PrintStream ps) throws AlgebricksException {
- long msb = LongPointable.getLong(b, s + 1);
- long lsb = LongPointable.getLong(b, s + 9);
-
- ps.print("\"" + AUUID.toStringLiteralOnly(msb, lsb) + "\"");
+ StringBuilder buf = new StringBuilder(AUUID.UUID_CHARS + 2);
+ buf.append('"');
+ AUUID.appendLiteralOnly(b, s + 1, buf).append('"');
+ ps.print(buf.toString());
}
}
diff --git a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AUUIDSerializerDeserializer.java b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AUUIDSerializerDeserializer.java
index 8df0b0d..9ed398e 100644
--- a/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AUUIDSerializerDeserializer.java
+++ b/asterix-om/src/main/java/org/apache/asterix/dataflow/data/nontagged/serde/AUUIDSerializerDeserializer.java
@@ -21,12 +21,10 @@
import java.io.DataInput;
import java.io.DataOutput;
-import java.io.IOException;
import org.apache.asterix.om.base.AUUID;
import org.apache.hyracks.api.dataflow.value.ISerializerDeserializer;
import org.apache.hyracks.api.exceptions.HyracksDataException;
-import org.apache.hyracks.dataflow.common.data.marshalling.Integer64SerializerDeserializer;
public class AUUIDSerializerDeserializer implements ISerializerDeserializer<AUUID> {
@@ -39,20 +37,12 @@
@Override
public AUUID deserialize(DataInput in) throws HyracksDataException {
- long msb = Integer64SerializerDeserializer.INSTANCE.deserialize(in);
- long lsb = Integer64SerializerDeserializer.INSTANCE.deserialize(in);
- // for each deserialization, a new object is created. maybe we should change this.
- return new AUUID(msb, lsb);
+ return AUUID.readFrom(in);
}
@Override
public void serialize(AUUID instance, DataOutput out) throws HyracksDataException {
- try {
- Integer64SerializerDeserializer.INSTANCE.serialize(instance.getMostSignificantBits(), out);
- Integer64SerializerDeserializer.INSTANCE.serialize(instance.getLeastSignificantBits(), out);
- } catch (IOException e) {
- throw new HyracksDataException(e);
- }
+ instance.writeTo(out);
}
}
diff --git a/asterix-om/src/main/java/org/apache/asterix/om/base/AGeneratedUUID.java b/asterix-om/src/main/java/org/apache/asterix/om/base/AGeneratedUUID.java
new file mode 100644
index 0000000..da1b35b
--- /dev/null
+++ b/asterix-om/src/main/java/org/apache/asterix/om/base/AGeneratedUUID.java
@@ -0,0 +1,62 @@
+/*
+ * 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.asterix.om.base;
+
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class AGeneratedUUID extends AUUID {
+
+ private static class Holder {
+ static final byte [] hostUnique = new byte[4];
+
+ static {
+ new SecureRandom().nextBytes(hostUnique);
+ }
+ }
+ static final Random random = new Random();
+ static final AtomicInteger nextInstance = new AtomicInteger(random.nextInt());
+
+ public AGeneratedUUID() {
+ int unique = nextInstance.getAndIncrement();
+
+ // fill with pseudo-random bytes
+ random.nextBytes(uuidBytes);
+
+ // overwrite the first four bytes with the host unique value
+ System.arraycopy(Holder.hostUnique, 0, uuidBytes, 0, 4);
+
+ // overwrite the next four bytes with the thread unique value
+ uuidBytes[5] = (byte)(unique >> 24);
+ uuidBytes[6] = (byte)(unique >> 16);
+ uuidBytes[7] = (byte)(unique >> 8);
+ uuidBytes[8] = (byte)unique;
+ }
+
+ public void nextUUID() {
+ // increment the UUID value
+ for (int i = UUID_BYTES - 1; i >= 8; i--) {
+ if (++uuidBytes[i] != 0) {
+ break;
+ }
+ }
+ }
+}
diff --git a/asterix-om/src/main/java/org/apache/asterix/om/base/AMutableUUID.java b/asterix-om/src/main/java/org/apache/asterix/om/base/AMutableUUID.java
index 48946de..c9e581c 100644
--- a/asterix-om/src/main/java/org/apache/asterix/om/base/AMutableUUID.java
+++ b/asterix-om/src/main/java/org/apache/asterix/om/base/AMutableUUID.java
@@ -19,46 +19,107 @@
package org.apache.asterix.om.base;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
public class AMutableUUID extends AUUID {
- private final long[] uuidBits;
- private final byte[] randomBytes;
- public AMutableUUID(long msb, long lsb) {
- super(msb, lsb);
- randomBytes = new byte[16];
- uuidBits = new long[2];
+ public void parseUUIDString(String tokenImage) throws HyracksDataException {
+ if (tokenImage.length() != UUID_CHARS) {
+ throw new HyracksDataException("This is not a correct UUID value: " + tokenImage);
+ }
+ byte [] hexBytes = new byte[UUID_CHARS];
+ for (int i = 0; i < tokenImage.length(); i++) {
+ hexBytes[i] = (byte)tokenImage.charAt(i);
+ }
+ parseUUIDHexBytes(hexBytes, 0);
}
- public void nextUUID() {
- Holder.srnd.nextBytes(randomBytes);
- uuidBitsFromBytes(uuidBits, randomBytes);
- msb = uuidBits[0];
- lsb = uuidBits[1];
+ public void parseUUIDHexBytes(byte[] serString, int offset) throws HyracksDataException {
+ // First part - 8 bytes
+ decodeBytesFromHex(serString, offset, uuidBytes, 0, 8);
+ offset += 8;
+
+ // Skip the hyphen part
+ offset += 1;
+
+ // Second part - 4 bytes
+ decodeBytesFromHex(serString, offset, uuidBytes, 4, 4);
+ offset += 4;
+
+ // Skip the hyphen part
+ offset += 1;
+
+ // Third part - 4 bytes
+ decodeBytesFromHex(serString, offset, uuidBytes, 6, 4);
+ offset += 4;
+
+ // Skip the hyphen part
+ offset += 1;
+
+ // Fourth part - 4 bytes
+ decodeBytesFromHex(serString, offset, uuidBytes, 8, 4);
+ offset += 4;
+
+ // Skip the hyphen part
+ offset += 1;
+
+ // The last part - 12 bytes
+ decodeBytesFromHex(serString, offset, uuidBytes, 10, 12);
}
- // Set the most significant bits and the least significant bits.
- public void setValue(long msb, long lsb) {
- this.msb = msb;
- this.lsb = lsb;
+ // Calculate a long value from a hex string.
+ private static void decodeBytesFromHex(byte[] hexArray, int hexArrayOffset, byte[] outputArray, int outputOffset, int length)
+ throws HyracksDataException {
+ for (int i = hexArrayOffset; i < hexArrayOffset + length; ) {
+ int hi = transformHexCharToInt(hexArray[i++]);
+ outputArray[outputOffset++] = (byte) (hi << 4 | transformHexCharToInt(hexArray[i++]));
+ }
}
- // Since AUUID is a wrapper of java.util.uuid,
- // we can use the same method that creates a UUID from a String.
- public void fromStringToAMuatbleUUID(String value) {
- String[] components = value.split("-");
- if (components.length != 5)
- throw new IllegalArgumentException("Invalid UUID string: " + value);
- for (int i = 0; i < 5; i++)
- components[i] = "0x" + components[i];
-
- msb = Long.decode(components[0]).longValue();
- msb <<= 16;
- msb |= Long.decode(components[1]).longValue();
- msb <<= 16;
- msb |= Long.decode(components[2]).longValue();
-
- lsb = Long.decode(components[3]).longValue();
- lsb <<= 48;
- lsb |= Long.decode(components[4]).longValue();
+ // Interpret a character to the corresponding integer value.
+ private static int transformHexCharToInt(byte val) throws HyracksDataException {
+ switch (val) {
+ case '0':
+ return 0;
+ case '1':
+ return 1;
+ case '2':
+ return 2;
+ case '3':
+ return 3;
+ case '4':
+ return 4;
+ case '5':
+ return 5;
+ case '6':
+ return 6;
+ case '7':
+ return 7;
+ case '8':
+ return 8;
+ case '9':
+ return 9;
+ case 'a':
+ case 'A':
+ return 10;
+ case 'b':
+ case 'B':
+ return 11;
+ case 'c':
+ case 'C':
+ return 12;
+ case 'd':
+ case 'D':
+ return 13;
+ case 'e':
+ case 'E':
+ return 14;
+ case 'f':
+ case 'F':
+ return 15;
+ default:
+ throw new HyracksDataException("This is not a correct UUID value.");
+ }
}
+
}
diff --git a/asterix-om/src/main/java/org/apache/asterix/om/base/AUUID.java b/asterix-om/src/main/java/org/apache/asterix/om/base/AUUID.java
index bb54988..329ae53 100644
--- a/asterix-om/src/main/java/org/apache/asterix/om/base/AUUID.java
+++ b/asterix-om/src/main/java/org/apache/asterix/om/base/AUUID.java
@@ -19,85 +19,42 @@
package org.apache.asterix.om.base;
-import java.security.SecureRandom;
-import java.util.UUID;
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Arrays;
import org.apache.asterix.common.exceptions.AsterixException;
import org.apache.asterix.om.types.BuiltinType;
import org.apache.asterix.om.types.IAType;
import org.apache.asterix.om.visitors.IOMVisitor;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
import org.json.JSONException;
import org.json.JSONObject;
public class AUUID implements IAObject {
- protected static class Holder {
- static final SecureRandom srnd = new SecureRandom();
- }
+ public static final int UUID_CHARS = 36;
+ public static final int UUID_BYTES = 16;
- protected long msb;
- protected long lsb;
+ protected final byte [] uuidBytes;
- public AUUID(UUID uuid) {
- msb = uuid.getMostSignificantBits();
- lsb = uuid.getLeastSignificantBits();
- }
+ protected static final char [] CHARS;
- public AUUID(long msb, long lsb) {
- this.msb = msb;
- this.lsb = lsb;
- }
- public long getMostSignificantBits() {
- return msb;
- }
-
- public long getLeastSignificantBits() {
- return lsb;
- }
-
- public static AUUID randomUUID() {
- long[] bits = new long[2];
- byte[] randomBytes = new byte[16];
- Holder.srnd.nextBytes(randomBytes);
- uuidBitsFromBytes(bits, randomBytes);
- return new AUUID(bits[0], bits[1]);
- }
-
- public void generateNextRandomUUID() {
- byte[] randomBytes = new byte[16];
- Holder.srnd.nextBytes(randomBytes);
- uuidBitsFromBytes(randomBytes);
- }
-
- protected void uuidBitsFromBytes(byte[] randomBytes) {
- this.msb = 0;
- this.lsb = 0;
- randomBytes[6] &= 0x0f; /* clear version */
- randomBytes[6] |= 0x40; /* set to version 4 */
- randomBytes[8] &= 0x3f; /* clear variant */
- randomBytes[8] |= 0x80; /* set to IETF variant */
- for (int i = 0; i < 8; ++i) {
- this.msb = (this.msb << 8) | (randomBytes[i] & 0xff);
- }
- for (int i = 8; i < 16; ++i) {
- this.lsb = (this.lsb << 8) | (randomBytes[i] & 0xff);
+ static {
+ CHARS = new char [16];
+ for (int i = 0; i < 16; i++) {
+ CHARS[i] = Character.forDigit(i, 16);
}
}
- protected static void uuidBitsFromBytes(long[] bits, byte[] randomBytes) {
- bits[0] = 0;
- bits[1] = 0;
- randomBytes[6] &= 0x0f; /* clear version */
- randomBytes[6] |= 0x40; /* set to version 4 */
- randomBytes[8] &= 0x3f; /* clear variant */
- randomBytes[8] |= 0x80; /* set to IETF variant */
- for (int i = 0; i < 8; ++i) {
- bits[0] = (bits[0] << 8) | (randomBytes[i] & 0xff);
- }
- for (int i = 8; i < 16; ++i) {
- bits[1] = (bits[1] << 8) | (randomBytes[i] & 0xff);
- }
+ protected AUUID() {
+ this(new byte[UUID_BYTES]);
+ }
+
+ public AUUID(byte [] bytes) {
+ this.uuidBytes = bytes;
}
@Override
@@ -123,55 +80,57 @@
return false;
}
AUUID oUUID = (AUUID) obj;
- return oUUID.msb == this.msb && oUUID.lsb == this.lsb;
+ return Arrays.equals(oUUID.uuidBytes, this.uuidBytes);
}
@Override
public int hash() {
- long hilo = msb ^ lsb;
- return ((int) (hilo >> 32)) ^ (int) hilo;
+ return Arrays.hashCode(uuidBytes);
}
@Override
public String toString() {
- return "AUUID: {" + toStringLiteralOnly(msb, lsb) + "}";
-
+ StringBuilder buf = new StringBuilder(UUID_CHARS + 9);
+ buf.append("AUUID: {");
+ return appendLiteralOnly(buf).append('}').toString();
}
- public String toStringLiteralOnly() {
- return toStringLiteralOnly(msb, lsb);
+ public StringBuilder appendLiteralOnly(StringBuilder buf) {
+ return appendLiteralOnly(uuidBytes, 0, buf);
}
- public static String toStringLiteralOnly(long msbValue, long lsbValue) {
- return digits(msbValue >> 32, 8) + "-" + digits(msbValue >> 16, 4) + "-" + digits(msbValue, 4) + "-"
- + digits(lsbValue >> 48, 4) + "-" + digits(lsbValue, 12);
-
+ private static StringBuilder digits(byte b [], int offset, int count, StringBuilder result) {
+ for (int i = 0; i < count; i++) {
+ result.append(CHARS[(b[offset + i] >> 4) & 0xf]);
+ result.append(CHARS[b[offset + i] & 0xf]);
+ }
+ return result;
}
- // Since AUUID is a wrapper of java.util.uuid,
- // we can use the same method that creates a UUID from a String.
- public static AUUID fromString(String name) {
- String[] components = name.split("-");
- if (components.length != 5)
- throw new IllegalArgumentException("Invalid UUID string: " + name);
- for (int i = 0; i < 5; i++)
- components[i] = "0x" + components[i];
-
- long msb = Long.decode(components[0]).longValue();
- msb <<= 16;
- msb |= Long.decode(components[1]).longValue();
- msb <<= 16;
- msb |= Long.decode(components[2]).longValue();
-
- long lsb = Long.decode(components[3]).longValue();
- lsb <<= 48;
- lsb |= Long.decode(components[4]).longValue();
-
- return new AUUID(msb, lsb);
+ public static StringBuilder appendLiteralOnly(byte [] bytes, int offset, StringBuilder result) {
+ digits(bytes, offset, 4, result).append('-');
+ digits(bytes, offset + 4, 2, result).append('-');
+ digits(bytes, offset + 6, 2, result).append('-');
+ digits(bytes, offset + 8, 2, result).append('-');
+ return digits(bytes, offset + 10, 6, result);
}
- private static String digits(long val, int digits) {
- long hi = 1L << (digits * 4);
- return Long.toHexString(hi | (val & (hi - 1))).substring(1);
+ public void writeTo(DataOutput out) throws HyracksDataException {
+ try {
+ out.write(uuidBytes);
+ } catch (IOException e) {
+ throw new HyracksDataException(e);
+ }
}
+
+ public static AUUID readFrom(DataInput in) throws HyracksDataException {
+ AUUID instance = new AUUID();
+ try {
+ in.readFully(instance.uuidBytes);
+ } catch (IOException e) {
+ throw new HyracksDataException(e);
+ }
+ return instance;
+ }
+
}
diff --git a/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AUUIDFromStringConstructorDescriptor.java b/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AUUIDFromStringConstructorDescriptor.java
index c7168c4..b5caf18 100644
--- a/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AUUIDFromStringConstructorDescriptor.java
+++ b/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/constructors/AUUIDFromStringConstructorDescriptor.java
@@ -69,16 +69,15 @@
private ArrayBackedValueStorage outInput = new ArrayBackedValueStorage();
private ICopyEvaluator eval = args[0].createEvaluator(outInput);
private String errorMessage = "This can not be an instance of UUID";
- private AMutableUUID aUUID = new AMutableUUID(0, 0);
+ private AMutableUUID uuid = new AMutableUUID();
@SuppressWarnings("unchecked")
private ISerializerDeserializer<AUUID> uuidSerde = AqlSerializerDeserializerProvider.INSTANCE
.getSerializerDeserializer(BuiltinType.AUUID);
@SuppressWarnings("unchecked")
private ISerializerDeserializer<ANull> nullSerde = AqlSerializerDeserializerProvider.INSTANCE
.getSerializerDeserializer(BuiltinType.ANULL);
- private long msb = 0;
- private long lsb = 0;
- private long tmpLongValue = 0;
+
+
private final UTF8StringPointable utf8Ptr = new UTF8StringPointable();
@@ -90,51 +89,12 @@
byte[] serString = outInput.getByteArray();
if (serString[0] == ATypeTag.SERIALIZED_STRING_TYPE_TAG) {
utf8Ptr.set(serString, 1, outInput.getLength() - 1);
- msb = 0;
- lsb = 0;
- tmpLongValue = 0;
// first byte: tag, next x bytes: length
int offset = utf8Ptr.getCharStartOffset();
- // First part - 8 bytes
- msb = calculateLongFromHex(serString, offset, 8);
- msb <<= 16;
- offset += 8;
- // Skip the hyphen part
- offset += 1;
-
- // Second part - 4 bytes
- tmpLongValue = calculateLongFromHex(serString, offset, 4);
- msb |= tmpLongValue;
- msb <<= 16;
- offset += 4;
-
- // Skip the hyphen part
- offset += 1;
-
- // Third part - 4 bytes
- tmpLongValue = calculateLongFromHex(serString, offset, 4);
- msb |= tmpLongValue;
- offset += 4;
-
- // Skip the hyphen part
- offset += 1;
-
- // Fourth part - 4 bytes
- lsb = calculateLongFromHex(serString, offset, 4);
- lsb <<= 48;
- offset += 4;
-
- // Skip the hyphen part
- offset += 1;
-
- // The last part - 12 bytes
- tmpLongValue = calculateLongFromHex(serString, offset, 12);
- lsb |= tmpLongValue;
-
- aUUID.setValue(msb, lsb);
- uuidSerde.serialize(aUUID, out);
+ uuid.parseUUIDHexBytes(serString, offset);
+ uuidSerde.serialize(uuid, out);
} else if (serString[0] == ATypeTag.SERIALIZED_NULL_TYPE_TAG)
nullSerde.serialize(ANull.NULL, out);
@@ -145,70 +105,6 @@
}
}
- // Calculate a long value from a hex string.
- private long calculateLongFromHex(byte[] hexArray, int offset, int length)
- throws AlgebricksException {
- int tmpIntVal = 0;
- long tmpLongVal = 0;
- for (int i = offset; i < offset + length; i++) {
- tmpIntVal = transformHexCharToInt(hexArray[i]);
- if (tmpIntVal != -1) {
- tmpLongVal = tmpLongVal * 16 + tmpIntVal;
- } else {
- throw new AlgebricksException("This is not a correct UUID value.");
- }
- }
- return tmpLongVal;
- }
-
- // Interpret a character to the corresponding integer value.
- private int transformHexCharToInt(byte val) throws AlgebricksException {
- switch (val) {
- case '0':
- return 0;
- case '1':
- return 1;
- case '2':
- return 2;
- case '3':
- return 3;
- case '4':
- return 4;
- case '5':
- return 5;
- case '6':
- return 6;
- case '7':
- return 7;
- case '8':
- return 8;
- case '9':
- return 9;
- case 'a':
- case 'A':
- return 10;
- case 'b':
- case 'B':
- return 11;
- case 'c':
- case 'C':
- return 12;
- case 'd':
- case 'D':
- return 13;
- case 'e':
- case 'E':
- return 14;
- case 'f':
- case 'F':
- return 15;
- case '-':
- // We need to skip this hyphen part.
- return -1;
- default:
- throw new AlgebricksException("This is not a correct UUID value.");
- }
- }
};
}
};
diff --git a/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CreateUUIDDescriptor.java b/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CreateUUIDDescriptor.java
index 587581e..be2f700 100644
--- a/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CreateUUIDDescriptor.java
+++ b/asterix-runtime/src/main/java/org/apache/asterix/runtime/evaluators/functions/CreateUUIDDescriptor.java
@@ -19,7 +19,7 @@
package org.apache.asterix.runtime.evaluators.functions;
import org.apache.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
-import org.apache.asterix.om.base.AMutableUUID;
+import org.apache.asterix.om.base.AGeneratedUUID;
import org.apache.asterix.om.base.AUUID;
import org.apache.asterix.om.functions.AsterixBuiltinFunctions;
import org.apache.asterix.om.functions.IFunctionDescriptor;
@@ -58,7 +58,7 @@
@Override
public ICopyEvaluator createEvaluator(final IDataOutputProvider output) throws AlgebricksException {
return new ICopyEvaluator() {
- final AMutableUUID uuid = new AMutableUUID(0, 0);
+ final AGeneratedUUID uuid = new AGeneratedUUID();
@Override
public void evaluate(IFrameTupleReference tuple) throws AlgebricksException {