blob: 2b251e725fcd0b7849286fd60ffa05997174ae1a [file]
/*
*
* 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);
}
}