| /* |
| * |
| * Derby - Class OERandom |
| * |
| * 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.derbyTesting.system.oe.util; |
| |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.util.Random; |
| |
| import org.apache.derbyTesting.system.oe.client.Load; |
| |
| /** |
| * Methods to implement the random database population types |
| * for the Order Entry Benchmark. The rules for generating |
| * the random data is per the TPC-C specification. |
| */ |
| public class OERandom { |
| |
| final Random rand; |
| |
| protected final int Clast; |
| |
| protected final int Cid; |
| |
| protected final int Citem; |
| |
| /** |
| * Create a matching OERandom, for use in multi-threaded |
| * runs where all the submitters need to share the same |
| * Clast, Cid and Citem values. |
| * @param oer |
| */ |
| public OERandom(OERandom oer) { |
| // Since these objects may be created at the same time, |
| // within the resolution of currentTimeMillis(), then |
| // ensure they have different seeds. |
| rand = new Random(System.currentTimeMillis() + oer.rand.nextLong()); |
| Clast = oer.Clast; |
| Cid = oer.Cid; |
| Citem = oer.Citem; |
| } |
| |
| public OERandom(int last, long seed) { |
| |
| rand = new Random(seed); |
| Clast = last; |
| Cid = this.randomInt(0, 255); |
| Citem = this.randomInt(0, 255); |
| |
| initAStrings(); |
| } |
| |
| public OERandom(int last) { |
| this(last, System.currentTimeMillis()); |
| } |
| |
| private static int[] RESCALE = { 0, 10, 100, 1000, 10000, 100000, 1000000 }; |
| |
| private StringBuffer decimalString = new StringBuffer(12); |
| |
| public String randomDecimalString(int start, int end, int scale) { |
| |
| int val = randomInt(start, end); |
| |
| int whole = val / RESCALE[scale]; |
| |
| int part = val % RESCALE[scale]; |
| |
| decimalString.setLength(0); |
| decimalString.append(whole); |
| decimalString.append('.'); |
| |
| int pos = decimalString.length(); |
| |
| decimalString.append(part); |
| |
| int tempScale = decimalString.length() - pos; |
| if (tempScale < scale) { |
| for (int i = 0; i < (scale - tempScale); i++) |
| decimalString.insert(pos, '0'); |
| } |
| |
| return decimalString.toString(); |
| } |
| |
| /** |
| * Payment amount between 1.00 and 5,000.00 |
| * @return Payment amount between 1.00 and 5,000.00 |
| */ |
| public BigDecimal payment() |
| { |
| return randomDecimal(1, 500000, 2); |
| } |
| |
| public BigDecimal randomDecimal(int start, int end, int scale) { |
| BigInteger bi = BigInteger.valueOf(randomInt(start, end)); |
| return new BigDecimal(bi, scale); |
| } |
| |
| /** |
| * tpcc 4.3.2.5 Implements random within [x .. y ] for int |
| */ |
| public int randomInt(int start, int end) { |
| double drand = rand.nextDouble(); |
| |
| double rrand = (drand * (end - start)) + 0.5; |
| |
| return ((int) rrand) + start; |
| } |
| |
| /** |
| * Return a random district [1..10] |
| */ |
| public short district() |
| { |
| return (short) randomInt(1, 10); |
| } |
| |
| /** |
| * Return a random carrier [1..10] |
| */ |
| public short carrier() |
| { |
| return (short) randomInt(1, 10); |
| } |
| |
| /** |
| * Return a random threshold for the stock level [10..20] |
| */ |
| public int threshold() |
| { |
| return randomInt(10, 20); |
| } |
| |
| /** |
| * tpcc 4.3.2.2 (random a string) |
| */ |
| public String randomAString(int min, int max) { |
| int len = randomInt(min, max); |
| char[] c = new char[len]; |
| for (int i = 0; i < len; i++) { |
| |
| double drand = rand.nextDouble(); |
| |
| if (i == 0) { |
| if (drand < 2.0) |
| c[0] = (char) randomInt((int) 'A', (int) 'Z'); |
| else { |
| switch (randomInt(1, 10)) { |
| case 1: |
| c[0] = '\u00c0'; |
| break; |
| case 2: |
| c[0] = '\u00c1'; |
| break; |
| case 3: |
| c[0] = '\u00c2'; |
| break; |
| case 4: |
| c[0] = '\u00ca'; |
| break; |
| case 5: |
| c[0] = '\u00cb'; |
| break; |
| case 6: |
| c[0] = '\u00d4'; |
| break; |
| case 7: |
| c[0] = '\u00d8'; |
| break; |
| case 8: |
| c[0] = '\u00d1'; |
| break; |
| case 9: |
| c[0] = '\u00cd'; |
| break; |
| default: |
| c[0] = '\u00dc'; |
| break; |
| } |
| } |
| |
| continue; |
| } |
| |
| if (drand < 2.0) |
| c[i] = (char) randomInt((int) 'a', (int) 'z'); |
| else { |
| switch (randomInt(1, 10)) { |
| case 1: |
| c[i] = '\u00e2'; |
| break; |
| case 2: |
| c[i] = '\u00e4'; |
| break; |
| case 3: |
| c[i] = '\u00e7'; |
| break; |
| case 4: |
| c[i] = '\u00e8'; |
| break; |
| case 5: |
| c[i] = '\u00ec'; |
| break; |
| case 6: |
| c[i] = '\u00ef'; |
| break; |
| case 7: |
| c[i] = '\u00f6'; |
| break; |
| case 8: |
| c[i] = '\u00f9'; |
| break; |
| case 9: |
| c[i] = '\u00fc'; |
| break; |
| default: |
| c[i] = '\u00e5'; |
| break; |
| } |
| } |
| } |
| |
| return new String(c); |
| } |
| |
| /** |
| * tpcc 4.3.2.2 (random n string) |
| */ |
| public String randomNString(int min, int max) { |
| int len = randomInt(min, max); |
| char[] c = new char[len]; |
| for (int i = 0; i < len; i++) { |
| c[i] = (char) randomInt((int) '0', (int) '9'); |
| } |
| |
| return new String(c); |
| } |
| |
| /** |
| * tpcc 4.3.2.3 |
| */ |
| private final String[] SYLLABLES = { "BAR", "OUGHT", "ABLE", "PRI", "PRES", |
| "ESE", "ANTI", "CALLY", "ATION", "EING" }; |
| |
| protected String randomCLast(int n) { |
| |
| return SYLLABLES[n / 100] + SYLLABLES[(n / 10) % 10] |
| + SYLLABLES[n % 10]; |
| } |
| |
| /** |
| * Generate the zipcode value |
| * return zipcode value according to the requirements specified in |
| * Clause 4.3.2.7 of TPC-C spec |
| */ |
| public String randomZIP() { |
| return randomNString(4, 4) + "11111"; |
| } |
| |
| /** |
| * Section 2.1.6 of TPC-C specification, for OL_I_ID NURand(A, x, y) = |
| * (((random(0, A) | random(x, y)) + C) % (y - x + 1)) + x C is a run-time |
| * constant randomly chosen within [0 .. A] NURand(8191, 1,100000) |
| * |
| * @return nonuniform random number |
| */ |
| public int NURand8191() { |
| int l = randomInt(0, 8191); |
| int r = randomInt(1, Load.ITEM_COUNT); |
| int C = randomInt(0, 8191); |
| return ((l | r) + C) % (Load.ITEM_COUNT - 1 + 1) + 1; |
| } |
| |
| /** |
| * Section 2.1.6 of TPC-C specification for CID NURand(A, x, y) = |
| * (((random(0, A) | random(x, y)) + C) % (y - x + 1)) + x NURand(1023, |
| * 1,3000) |
| * |
| * @return nonuniform random number |
| */ |
| public int NURand1023() { |
| int l = randomInt(0, 1023); |
| int r = randomInt(1, (Load.CUSTOMER_COUNT_W / Load.DISTRICT_COUNT_W)); |
| int C = randomInt(0, 1023); |
| return ((l | r) + C) |
| % ((Load.CUSTOMER_COUNT_W / Load.DISTRICT_COUNT_W) - 1 + 1) + 1; |
| } |
| |
| /** |
| * Section 2.1.6 of TPC-C specification, for C_LAST NURand(A, x, y) = |
| * (((random(0, A) | random(x, y)) + C) % (y - x + 1)) + x NURand(255,0,999) |
| * |
| * @return nonuniform random number |
| */ |
| public int NURand255() { |
| int l = randomInt(0, 255); |
| int r = randomInt(0, 999); |
| int C = randomInt(0, 255); |
| return ((l | r) + C) % (999 - 0 + 1) + 0; |
| } |
| |
| public String randomState() { |
| StringBuffer s = new StringBuffer(2); |
| for (int i = 0; i < 2; i++) { |
| s.append((char) randomInt((int) 'A', (int) 'Z')); |
| } |
| |
| return s.toString(); |
| } |
| |
| /** |
| * Clause 4.3.2.3 of the TPC-C specification |
| * @param cid - customer id. |
| * @return the generated Customer's last name per the requirements |
| * in the TPC-C spec. |
| */ |
| public String randomCLastPopulate(int cid) { |
| |
| // First thousand customers (C_ID is one based) |
| // have a fixed last name based upon the contiguous |
| // values from 0-999, section 4.3.3.1 |
| if (cid <= 1000) |
| return randomCLast(cid-1); // range 0 - 999 |
| |
| return randomCLast(NURand255()); |
| } |
| |
| public String randomCLast() { |
| return randomCLast(NURand255()); |
| } |
| |
| /** |
| * Clause 4.3.3.1 of TPC-C spec. random a-string [26 .. 50]. For 10% |
| * of the rows, selected at random, the string "ORIGINAL" must be held by 8 |
| * consecutive characters starting at a random position within the string |
| * |
| * @return string data per the TPC-C requirements |
| */ |
| public String randomData() { |
| String s = randomAString26_50(); |
| if (rand.nextDouble() < 0.9) |
| return s; |
| |
| int pos = randomInt(0, s.length() - 9); |
| |
| if (pos == 0) |
| return "ORIGINAL" + s.substring(8); |
| |
| if (pos == (s.length() - 9)) |
| return s.substring(0, s.length() - 9) + "ORIGINAL"; |
| |
| return s.substring(0, pos) + "ORIGINAL" |
| + s.substring(pos + 8, s.length()); |
| } |
| |
| public int[] randomIntPerm(int count) { |
| int[] data = new int[count]; |
| |
| for (int i = 0; i < count; i++) { |
| data[i] = i + 1; |
| } |
| |
| for (int j = 0; j < (count * 4); j++) { |
| |
| int a = randomInt(0, count - 1); |
| int b = randomInt(0, count - 1); |
| |
| int val = data[a]; |
| data[a] = data[b]; |
| data[b] = val; |
| } |
| return data; |
| } |
| |
| private final static String[] left24 = new String[10]; |
| |
| private final static String[] left300 = new String[10]; |
| |
| private final static String[] right200 = new String[10]; |
| |
| private final static String[] left10 = new String[10]; |
| |
| private final static String[] right10 = new String[10]; |
| |
| private final static String[] left14 = new String[10]; |
| |
| private final static String[] left26 = new String[10]; |
| |
| private final static String[] right24 = new String[10]; |
| |
| private final static String[] left8 = new String[10]; |
| |
| private final static String[] right8 = new String[10]; |
| |
| private static boolean doneInit; |
| |
| private void initAStrings() { |
| |
| synchronized (left24) { |
| if (doneInit) |
| return; |
| |
| for (int i = 0; i < 10; i++) { |
| // 24..24 |
| left24[i] = randomAString(24, 24); |
| |
| // 300...500 |
| left300[i] = randomAString(300, 300); |
| right200[i] = randomAString(0, 200); |
| |
| // 10...20 |
| left10[i] = randomAString(10, 10); |
| right10[i] = randomAString(0, 10); |
| |
| // 14 .. 24 |
| left14[i] = randomAString(10, 10); |
| |
| // 26 .. 50 |
| left26[i] = randomAString(26, 26); |
| right24[i] = randomAString(0, 24); |
| |
| // 8 .. 16 |
| left8[i] = randomAString(8, 8); |
| right8[i] = randomAString(0, 8); |
| |
| } |
| doneInit = true; |
| } |
| } |
| |
| public String randomAString24() { |
| return left24[randomInt(0, 9)]; |
| } |
| |
| /** |
| * Section 4.3.2.2(and comments 1 and 2). |
| * The notation random a-string [x .. y] (respectively, |
| * n-string [x ..y]) represents a string of random alphanumeric (respectively, |
| * numeric)characters of a random length of minimum x, maximum y, and mean (y+x)/2. |
| * |
| * @return string value. |
| */ |
| public String randomAString300_500() { |
| String l = left300[randomInt(0, 9)]; |
| String r = right200[randomInt(0, 9)]; |
| |
| return l.concat(r); |
| } |
| |
| public String randomAString10_20() { |
| String l = left10[randomInt(0, 9)]; |
| String r = right10[randomInt(0, 9)]; |
| |
| return l.concat(r); |
| } |
| |
| public String randomAString14_24() { |
| String l = left14[randomInt(0, 9)]; |
| String r = right10[randomInt(0, 9)]; |
| |
| return l.concat(r); |
| } |
| |
| public String randomAString26_50() { |
| String l = left26[randomInt(0, 9)]; |
| String r = right24[randomInt(0, 9)]; |
| |
| return l.concat(r); |
| } |
| |
| public String randomAString8_16() { |
| String l = left8[randomInt(0, 9)]; |
| String r = right8[randomInt(0, 9)]; |
| |
| return l.concat(r); |
| } |
| |
| } |