--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.services.uuid.BasicUUIDFactory\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.services.uuid;\r
+\r
+import org.apache.derby.iapi.services.monitor.Monitor;\r
+import org.apache.derby.catalog.UUID;\r
+import org.apache.derby.iapi.services.uuid.UUIDFactory;\r
+\r
+/**\r
+\r
+ A hack implementation of something similar to a DCE UUID \r
+ generator. Generates unique 128-bit numbers based on the\r
+ current machine's internet address, the current time, and\r
+ a sequence number. This implementation should be made to\r
+ conform to the DCE specification. ("DEC/HP, Network Computing\r
+ Architecture, Remote Procedure Call Runtime Extensions\r
+ Specification, version OSF TX1.0.11," Steven Miller, July\r
+ 23, 1992. This is part of the OSF DCE Documentation.\r
+ Chapter 10 describes the UUID generation algorithm.)\r
+ <P>\r
+ Some known deficiencies:\r
+ <ul>\r
+ <li> Rather than using the 48-bit hardware network address,\r
+ it uses the 32-bit IP address. IP addresses are not\r
+ guaranteed to be unique.\r
+ <li> There is no provision for generating a suitably unique\r
+ number if no IP address is available.\r
+ <li> Two processes running on this machine which start their\r
+ respective UUID services within a millisecond of one another\r
+ may generate duplicate UUIDS.\r
+ </ul>\r
+ <P>\r
+ However, the intention is that UUIDs generated from this class\r
+ will be unique with respect to UUIDs generated by other DCE\r
+ UUID generators.\r
+\r
+**/\r
+\r
+public final class BasicUUIDFactory\r
+ implements UUIDFactory\r
+{\r
+ /*\r
+ ** Fields of BasicUUIDFactory.\r
+ */\r
+\r
+ private long majorId; // 48 bits only\r
+ private long timemillis;\r
+\r
+ public BasicUUIDFactory() {\r
+ Object env = Monitor.getMonitor().getEnvironment();\r
+ if (env != null) {\r
+ String s = env.toString();\r
+ if (s != null)\r
+ env = s;\r
+\r
+ majorId = ((long) env.hashCode());\r
+\r
+ \r
+ } else {\r
+ majorId = Runtime.getRuntime().freeMemory();\r
+ }\r
+\r
+ majorId &= 0x0000ffffffffffffL;\r
+ resetCounters();\r
+ }\r
+\r
+\r
+ //\r
+ // Constants and fields for computing the sequence number. We started out with monotonically\r
+ // increasing sequence numbers but realized that this causes collisions at the\r
+ // ends of BTREEs built on UUID columns. So now we have a random number\r
+ // generator. We generate these numbers using a technique from Knuth\r
+ // "Seminumerical Algorithms," section 3.2 (Generating Uniform Random Numbers).\r
+ // The formula is:\r
+ //\r
+ // next = ( (MULTIPLIER * current) + STEP ) % MODULUS\r
+ //\r
+ // Here\r
+ //\r
+ // MODULUS = int size.\r
+ // MULTIPLIER = fairly close to the square root of MODULUS to force the\r
+ // sequence number to jump around. satisifies the rule that\r
+ // (MULTIPLIER-1) is divisible by 4 and by all the primes which\r
+ // divide MODULUS.\r
+ // STEP = a large number that keeps the sequence number jumping around.\r
+ // must be relatively prime to MODULUS.\r
+ // INITIAL_VALUE = a number guaranteeing that the first couple sequence numbers\r
+ // won't be monotonically increasing.\r
+ //\r
+ // The sequence numbers should jump around and cycle through all numbers which fit in an int.\r
+\r
+ private static final long MODULUS = ( 1L << 32 );\r
+ private static final long MULTIPLIER = ( ( 1L << 14 ) + 1 );\r
+ private static final long STEP = ( ( 1L << 27 ) + 1 );\r
+ private static final long INITIAL_VALUE = ( 2551218188L );\r
+\r
+ private long currentValue;\r
+\r
+ /*\r
+ ** Methods of UUID\r
+ */\r
+\r
+ /**\r
+ Generate a new UUID.\r
+ @see UUIDFactory#createUUID\r
+ **/\r
+ public synchronized UUID createUUID()\r
+ {\r
+ long cv = currentValue = ( ( MULTIPLIER * currentValue ) + STEP ) % MODULUS;\r
+ if ( cv == INITIAL_VALUE ) { bumpMajor(); }\r
+ int sequence = (int) cv;\r
+\r
+ return new BasicUUID(majorId, timemillis, sequence);\r
+ }\r
+\r
+ /**\r
+ Recreate a UUID previously generated UUID value.\r
+ @see UUIDFactory#recreateUUID\r
+ **/\r
+ public UUID recreateUUID(String uuidstring)\r
+ {\r
+ return new BasicUUID(uuidstring);\r
+ }\r
+\r
+ /**\r
+ @see UUIDFactory#recreateUUID\r
+ **/\r
+ public UUID recreateUUID(byte[] b)\r
+ {\r
+ return new BasicUUID(b);\r
+ }\r
+\r
+ private void bumpMajor() {\r
+\r
+ // 48 bits only\r
+ majorId = (majorId + 1L) & 0x0000ffffffffffffL;\r
+ if (majorId == 0L)\r
+ resetCounters();\r
+\r
+ }\r
+ private void resetCounters()\r
+ {\r
+ timemillis = System.currentTimeMillis();\r
+ currentValue = INITIAL_VALUE;\r
+ }\r
+}\r
+\r