diff --git a/core/src/main/java/com/yahoo/ycsb/workloads/CoreWorkload.java b/core/src/main/java/com/yahoo/ycsb/workloads/CoreWorkload.java index ad127d8b464aaf059f08495834b7cd257afde8bc..f90141bf324650d7249709a679bf4edff2d0fe8e 100644 --- a/core/src/main/java/com/yahoo/ycsb/workloads/CoreWorkload.java +++ b/core/src/main/java/com/yahoo/ycsb/workloads/CoreWorkload.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010 Yahoo! Inc. All rights reserved. + * Copyright (c) 2010 Yahoo! Inc., Copyright (c) 2016 YCSB contributors. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you * may not use this file except in compliance with the License. You @@ -371,17 +371,7 @@ public class CoreWorkload extends Workload { fieldnames.add("field" + i); } fieldlengthgenerator = CoreWorkload.getFieldLengthGenerator(p); - - double readproportion = Double.parseDouble( - p.getProperty(READ_PROPORTION_PROPERTY, READ_PROPORTION_PROPERTY_DEFAULT)); - double updateproportion = Double.parseDouble( - p.getProperty(UPDATE_PROPORTION_PROPERTY, UPDATE_PROPORTION_PROPERTY_DEFAULT)); - double insertproportion = Double.parseDouble( - p.getProperty(INSERT_PROPORTION_PROPERTY, INSERT_PROPORTION_PROPERTY_DEFAULT)); - double scanproportion = Double.parseDouble( - p.getProperty(SCAN_PROPORTION_PROPERTY, SCAN_PROPORTION_PROPERTY_DEFAULT)); - double readmodifywriteproportion = Double.parseDouble(p.getProperty( - READMODIFYWRITE_PROPORTION_PROPERTY, READMODIFYWRITE_PROPORTION_PROPERTY_DEFAULT)); + recordcount = Integer.parseInt(p.getProperty(Client.RECORD_COUNT_PROPERTY, Client.DEFAULT_RECORD_COUNT)); if (recordcount == 0) @@ -429,26 +419,7 @@ public class CoreWorkload extends Workload { } keysequence = new CounterGenerator(insertstart); - operationchooser = new DiscreteGenerator(); - if (readproportion > 0) { - operationchooser.addValue(readproportion, "READ"); - } - - if (updateproportion > 0) { - operationchooser.addValue(updateproportion, "UPDATE"); - } - - if (insertproportion > 0) { - operationchooser.addValue(insertproportion, "INSERT"); - } - - if (scanproportion > 0) { - operationchooser.addValue(scanproportion, "SCAN"); - } - - if (readmodifywriteproportion > 0) { - operationchooser.addValue(readmodifywriteproportion, "READMODIFYWRITE"); - } + operationchooser = createOperationGenerator(p); transactioninsertkeysequence = new AcknowledgedCounterGenerator(recordcount); if (requestdistrib.compareTo("uniform") == 0) { @@ -463,7 +434,8 @@ public class CoreWorkload extends Workload { // plus the number of predicted keys as the total keyspace. then, if the generator picks a key // that hasn't been inserted yet, will just ignore it and pick another key. this way, the size of // the keyspace doesn't change from the perspective of the scrambled zipfian generator - + final double insertproportion = Double.parseDouble( + p.getProperty(INSERT_PROPORTION_PROPERTY, INSERT_PROPORTION_PROPERTY_DEFAULT)); int opcount = Integer.parseInt(p.getProperty(Client.OPERATION_COUNT_PROPERTY)); int expectednewkeys = (int) ((opcount) * insertproportion * 2.0); // 2 is fudge factor @@ -801,4 +773,51 @@ public class CoreWorkload extends Workload { transactioninsertkeysequence.acknowledge(keynum); } } -} + + /** + * Creates a weighted discrete values with database operations for a workload to perform. + * Weights/proportions are read from the properties list and defaults are used + * when values are not configured. + * Current operations are "READ", "UPDATE", "INSERT", "SCAN" and "READMODIFYWRITE". + * @param p The properties list to pull weights from. + * @return A generator that can be used to determine the next operation to perform. + * @throws IllegalArgumentException if the properties object was null. + */ + public static DiscreteGenerator createOperationGenerator(final Properties p) { + if (p == null) { + throw new IllegalArgumentException("Properties object cannot be null"); + } + final double readproportion = Double.parseDouble( + p.getProperty(READ_PROPORTION_PROPERTY, READ_PROPORTION_PROPERTY_DEFAULT)); + final double updateproportion = Double.parseDouble( + p.getProperty(UPDATE_PROPORTION_PROPERTY, UPDATE_PROPORTION_PROPERTY_DEFAULT)); + final double insertproportion = Double.parseDouble( + p.getProperty(INSERT_PROPORTION_PROPERTY, INSERT_PROPORTION_PROPERTY_DEFAULT)); + final double scanproportion = Double.parseDouble( + p.getProperty(SCAN_PROPORTION_PROPERTY, SCAN_PROPORTION_PROPERTY_DEFAULT)); + final double readmodifywriteproportion = Double.parseDouble(p.getProperty( + READMODIFYWRITE_PROPORTION_PROPERTY, READMODIFYWRITE_PROPORTION_PROPERTY_DEFAULT)); + + final DiscreteGenerator operationchooser = new DiscreteGenerator(); + if (readproportion > 0) { + operationchooser.addValue(readproportion, "READ"); + } + + if (updateproportion > 0) { + operationchooser.addValue(updateproportion, "UPDATE"); + } + + if (insertproportion > 0) { + operationchooser.addValue(insertproportion, "INSERT"); + } + + if (scanproportion > 0) { + operationchooser.addValue(scanproportion, "SCAN"); + } + + if (readmodifywriteproportion > 0) { + operationchooser.addValue(readmodifywriteproportion, "READMODIFYWRITE"); + } + return operationchooser; + } +} \ No newline at end of file diff --git a/core/src/test/java/com/yahoo/ycsb/workloads/TestCoreWorkload.java b/core/src/test/java/com/yahoo/ycsb/workloads/TestCoreWorkload.java new file mode 100644 index 0000000000000000000000000000000000000000..d52f29b248cd069596ae1dd5bf9f8473e1fcaa64 --- /dev/null +++ b/core/src/test/java/com/yahoo/ycsb/workloads/TestCoreWorkload.java @@ -0,0 +1,70 @@ +/** + * Copyright (c) 2016 YCSB contributors. All rights reserved. + * + * Licensed 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. See accompanying + * LICENSE file. + */ +package com.yahoo.ycsb.workloads; + +import static org.testng.Assert.assertTrue; + +import java.util.Properties; + +import org.testng.annotations.Test; + +import com.yahoo.ycsb.generator.DiscreteGenerator; + +public class TestCoreWorkload { + + @Test + public void createOperationChooser() { + final Properties p = new Properties(); + p.setProperty(CoreWorkload.READ_PROPORTION_PROPERTY, "0.20"); + p.setProperty(CoreWorkload.UPDATE_PROPORTION_PROPERTY, "0.20"); + p.setProperty(CoreWorkload.INSERT_PROPORTION_PROPERTY, "0.20"); + p.setProperty(CoreWorkload.SCAN_PROPORTION_PROPERTY, "0.20"); + p.setProperty(CoreWorkload.READMODIFYWRITE_PROPORTION_PROPERTY, "0.20"); + final DiscreteGenerator generator = CoreWorkload.createOperationGenerator(p); + final int[] counts = new int[5]; + + for (int i = 0; i < 100; ++i) { + switch (generator.nextString()) { + case "READ": + ++counts[0]; + break; + case "UPDATE": + ++counts[1]; + break; + case "INSERT": + ++counts[2]; + break; + case "SCAN": + ++counts[3]; + break; + default: + ++counts[4]; + } + } + + for (int i : counts) { + // Doesn't do a wonderful job of equal distribution, but in a hundred, if we + // don't see at least one of each operation then the generator is really broke. + assertTrue(i > 1); + } + } + + @Test (expectedExceptions = IllegalArgumentException.class) + public void createOperationChooserNullProperties() { + CoreWorkload.createOperationGenerator(null); + } +} \ No newline at end of file