result) {
for (String col : columns) {
result.put(col, new StringByteIterator(structReader.getString(col)));
}
}
}
diff --git a/core/src/main/java/com/yahoo/ycsb/BasicDB.java b/core/src/main/java/com/yahoo/ycsb/BasicDB.java
index dab23a01..dfb88a0c 100644
--- a/core/src/main/java/com/yahoo/ycsb/BasicDB.java
+++ b/core/src/main/java/com/yahoo/ycsb/BasicDB.java
@@ -1,269 +1,270 @@
/**
* Copyright (c) 2010-2016 Yahoo! Inc., 2017 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;
import java.util.*;
+import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.LockSupport;
/**
* Basic DB that just prints out the requested operations, instead of doing them against a database.
*/
public class BasicDB extends DB {
public static final String VERBOSE = "basicdb.verbose";
public static final String VERBOSE_DEFAULT = "true";
public static final String SIMULATE_DELAY = "basicdb.simulatedelay";
public static final String SIMULATE_DELAY_DEFAULT = "0";
public static final String RANDOMIZE_DELAY = "basicdb.randomizedelay";
public static final String RANDOMIZE_DELAY_DEFAULT = "true";
private boolean verbose;
private boolean randomizedelay;
private int todelay;
public BasicDB() {
todelay = 0;
}
private void delay() {
if (todelay > 0) {
long delayNs;
if (randomizedelay) {
delayNs = TimeUnit.MILLISECONDS.toNanos(Utils.random().nextInt(todelay));
if (delayNs == 0) {
return;
}
} else {
delayNs = TimeUnit.MILLISECONDS.toNanos(todelay);
}
final long deadline = System.nanoTime() + delayNs;
do {
LockSupport.parkNanos(deadline - System.nanoTime());
} while (System.nanoTime() < deadline && !Thread.interrupted());
}
}
/**
* Initialize any state for this DB.
* Called once per DB instance; there is one DB instance per client thread.
*/
@SuppressWarnings("unchecked")
public void init() {
verbose = Boolean.parseBoolean(getProperties().getProperty(VERBOSE, VERBOSE_DEFAULT));
todelay = Integer.parseInt(getProperties().getProperty(SIMULATE_DELAY, SIMULATE_DELAY_DEFAULT));
randomizedelay = Boolean.parseBoolean(getProperties().getProperty(RANDOMIZE_DELAY, RANDOMIZE_DELAY_DEFAULT));
if (verbose) {
synchronized (System.out) {
System.out.println("***************** properties *****************");
Properties p = getProperties();
if (p != null) {
for (Enumeration e = p.propertyNames(); e.hasMoreElements();) {
String k = (String) e.nextElement();
System.out.println("\"" + k + "\"=\"" + p.getProperty(k) + "\"");
}
}
System.out.println("**********************************************");
}
}
}
protected static final ThreadLocal TL_STRING_BUILDER = new ThreadLocal() {
@Override
protected StringBuilder initialValue() {
return new StringBuilder();
}
};
protected static StringBuilder getStringBuilder() {
StringBuilder sb = TL_STRING_BUILDER.get();
sb.setLength(0);
return sb;
}
/**
* Read a record from the database. Each field/value pair from the result will be stored in a HashMap.
*
* @param table The name of the table
* @param key The record key of the record to read.
* @param fields The list of fields to read, or null for all of them
* @param result A HashMap of field/value pairs for the result
* @return Zero on success, a non-zero error code on error
*/
- public Status read(String table, String key, Set fields, HashMap result) {
+ public Status read(String table, String key, Set fields, Map result) {
delay();
if (verbose) {
StringBuilder sb = getStringBuilder();
sb.append("READ ").append(table).append(" ").append(key).append(" [ ");
if (fields != null) {
for (String f : fields) {
sb.append(f).append(" ");
}
} else {
sb.append("");
}
sb.append("]");
System.out.println(sb);
}
return Status.OK;
}
/**
* Perform a range scan for a set of records in the database. Each field/value pair from the result will be stored
* in a HashMap.
*
* @param table The name of the table
* @param startkey The record key of the first record to read.
* @param recordcount The number of records to read
* @param fields The list of fields to read, or null for all of them
* @param result A Vector of HashMaps, where each HashMap is a set field/value pairs for one record
* @return Zero on success, a non-zero error code on error
*/
public Status scan(String table, String startkey, int recordcount, Set fields,
Vector> result) {
delay();
if (verbose) {
StringBuilder sb = getStringBuilder();
sb.append("SCAN ").append(table).append(" ").append(startkey).append(" ").append(recordcount).append(" [ ");
if (fields != null) {
for (String f : fields) {
sb.append(f).append(" ");
}
} else {
sb.append("");
}
sb.append("]");
System.out.println(sb);
}
return Status.OK;
}
/**
* Update a record in the database. Any field/value pairs in the specified values HashMap will be written into the
* record with the specified record key, overwriting any existing values with the same field name.
*
* @param table The name of the table
* @param key The record key of the record to write.
* @param values A HashMap of field/value pairs to update in the record
* @return Zero on success, a non-zero error code on error
*/
- public Status update(String table, String key, HashMap values) {
+ public Status update(String table, String key, Map values) {
delay();
if (verbose) {
StringBuilder sb = getStringBuilder();
sb.append("UPDATE ").append(table).append(" ").append(key).append(" [ ");
if (values != null) {
for (Map.Entry entry : values.entrySet()) {
sb.append(entry.getKey()).append("=").append(entry.getValue()).append(" ");
}
}
sb.append("]");
System.out.println(sb);
}
return Status.OK;
}
/**
* Insert a record in the database. Any field/value pairs in the specified values HashMap will be written into the
* record with the specified record key.
*
* @param table The name of the table
* @param key The record key of the record to insert.
* @param values A HashMap of field/value pairs to insert in the record
* @return Zero on success, a non-zero error code on error
*/
- public Status insert(String table, String key, HashMap values) {
+ public Status insert(String table, String key, Map values) {
delay();
if (verbose) {
StringBuilder sb = getStringBuilder();
sb.append("INSERT ").append(table).append(" ").append(key).append(" [ ");
if (values != null) {
for (Map.Entry entry : values.entrySet()) {
sb.append(entry.getKey()).append("=").append(entry.getValue()).append(" ");
}
}
sb.append("]");
System.out.println(sb);
}
return Status.OK;
}
/**
* Delete a record from the database.
*
* @param table The name of the table
* @param key The record key of the record to delete.
* @return Zero on success, a non-zero error code on error
*/
public Status delete(String table, String key) {
delay();
if (verbose) {
StringBuilder sb = getStringBuilder();
sb.append("DELETE ").append(table).append(" ").append(key);
System.out.println(sb);
}
return Status.OK;
}
/**
* Short test of BasicDB
*/
/*
public static void main(String[] args) {
BasicDB bdb = new BasicDB();
Properties p = new Properties();
p.setProperty("Sky", "Blue");
p.setProperty("Ocean", "Wet");
bdb.setProperties(p);
bdb.init();
HashMap fields = new HashMap();
fields.put("A", "X");
fields.put("B", "Y");
bdb.read("table", "key", null, null);
bdb.insert("table", "key", fields);
fields = new HashMap();
fields.put("C", "Z");
bdb.update("table", "key", fields);
bdb.delete("table", "key");
}
*/
}
diff --git a/core/src/main/java/com/yahoo/ycsb/CommandLine.java b/core/src/main/java/com/yahoo/ycsb/CommandLine.java
index 9e95bd5a..ff781f41 100644
--- a/core/src/main/java/com/yahoo/ycsb/CommandLine.java
+++ b/core/src/main/java/com/yahoo/ycsb/CommandLine.java
@@ -1,349 +1,349 @@
/**
* Copyright (c) 2010 Yahoo! Inc. 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;
import com.yahoo.ycsb.workloads.CoreWorkload;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
/**
* A simple command line client to a database, using the appropriate com.yahoo.ycsb.DB implementation.
*/
public final class CommandLine {
private CommandLine() {
//not used
}
public static final String DEFAULT_DB = "com.yahoo.ycsb.BasicDB";
public static void usageMessage() {
System.out.println("YCSB Command Line Client");
System.out.println("Usage: java com.yahoo.ycsb.CommandLine [options]");
System.out.println("Options:");
System.out.println(" -P filename: Specify a property file");
System.out.println(" -p name=value: Specify a property value");
System.out.println(" -db classname: Use a specified DB class (can also set the \"db\" property)");
System.out.println(" -table tablename: Use the table name instead of the default \"" +
CoreWorkload.TABLENAME_PROPERTY_DEFAULT + "\"");
System.out.println();
}
public static void help() {
System.out.println("Commands:");
System.out.println(" read key [field1 field2 ...] - Read a record");
System.out.println(" scan key recordcount [field1 field2 ...] - Scan starting at key");
System.out.println(" insert key name1=value1 [name2=value2 ...] - Insert a new record");
System.out.println(" update key name1=value1 [name2=value2 ...] - Update a record");
System.out.println(" delete key - Delete a record");
System.out.println(" table [tablename] - Get or [set] the name of the table");
System.out.println(" quit - Quit");
}
public static void main(String[] args) {
Properties props = new Properties();
Properties fileprops = new Properties();
parseArguments(args, props, fileprops);
for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
String prop = (String) e.nextElement();
fileprops.setProperty(prop, props.getProperty(prop));
}
props = fileprops;
System.out.println("YCSB Command Line client");
System.out.println("Type \"help\" for command line help");
System.out.println("Start with \"-help\" for usage info");
String table = props.getProperty(CoreWorkload.TABLENAME_PROPERTY, CoreWorkload.TABLENAME_PROPERTY_DEFAULT);
//create a DB
String dbname = props.getProperty(Client.DB_PROPERTY, DEFAULT_DB);
ClassLoader classLoader = CommandLine.class.getClassLoader();
DB db = null;
try {
Class dbclass = classLoader.loadClass(dbname);
db = (DB) dbclass.newInstance();
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
db.setProperties(props);
try {
db.init();
} catch (DBException e) {
e.printStackTrace();
System.exit(0);
}
System.out.println("Connected.");
//main loop
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
//get user input
System.out.print("> ");
String input = null;
try {
input = br.readLine();
} catch (IOException e) {
e.printStackTrace();
System.exit(1);
}
if (input.compareTo("") == 0) {
continue;
}
if (input.compareTo("help") == 0) {
help();
continue;
}
if (input.compareTo("quit") == 0) {
break;
}
String[] tokens = input.split(" ");
long st = System.currentTimeMillis();
//handle commands
if (tokens[0].compareTo("table") == 0) {
handleTable(tokens, table);
} else if (tokens[0].compareTo("read") == 0) {
handleRead(tokens, table, db);
} else if (tokens[0].compareTo("scan") == 0) {
handleScan(tokens, table, db);
} else if (tokens[0].compareTo("update") == 0) {
handleUpdate(tokens, table, db);
} else if (tokens[0].compareTo("insert") == 0) {
handleInsert(tokens, table, db);
} else if (tokens[0].compareTo("delete") == 0) {
handleDelete(tokens, table, db);
} else {
System.out.println("Error: unknown command \"" + tokens[0] + "\"");
}
System.out.println((System.currentTimeMillis() - st) + " ms");
}
}
private static void parseArguments(String[] args, Properties props, Properties fileprops) {
int argindex = 0;
while ((argindex < args.length) && (args[argindex].startsWith("-"))) {
if ((args[argindex].compareTo("-help") == 0) ||
(args[argindex].compareTo("--help") == 0) ||
(args[argindex].compareTo("-?") == 0) ||
(args[argindex].compareTo("--?") == 0)) {
usageMessage();
System.exit(0);
}
if (args[argindex].compareTo("-db") == 0) {
argindex++;
if (argindex >= args.length) {
usageMessage();
System.exit(0);
}
props.setProperty(Client.DB_PROPERTY, args[argindex]);
argindex++;
} else if (args[argindex].compareTo("-P") == 0) {
argindex++;
if (argindex >= args.length) {
usageMessage();
System.exit(0);
}
String propfile = args[argindex];
argindex++;
Properties myfileprops = new Properties();
try {
myfileprops.load(new FileInputStream(propfile));
} catch (IOException e) {
System.out.println(e.getMessage());
System.exit(0);
}
for (Enumeration e = myfileprops.propertyNames(); e.hasMoreElements();) {
String prop = (String) e.nextElement();
fileprops.setProperty(prop, myfileprops.getProperty(prop));
}
} else if (args[argindex].compareTo("-p") == 0) {
argindex++;
if (argindex >= args.length) {
usageMessage();
System.exit(0);
}
int eq = args[argindex].indexOf('=');
if (eq < 0) {
usageMessage();
System.exit(0);
}
String name = args[argindex].substring(0, eq);
String value = args[argindex].substring(eq + 1);
props.put(name, value);
argindex++;
} else if (args[argindex].compareTo("-table") == 0) {
argindex++;
if (argindex >= args.length) {
usageMessage();
System.exit(0);
}
props.put(CoreWorkload.TABLENAME_PROPERTY, args[argindex]);
argindex++;
} else {
System.out.println("Unknown option " + args[argindex]);
usageMessage();
System.exit(0);
}
if (argindex >= args.length) {
break;
}
}
if (argindex != args.length) {
usageMessage();
System.exit(0);
}
}
private static void handleDelete(String[] tokens, String table, DB db) {
if (tokens.length != 2) {
System.out.println("Error: syntax is \"delete keyname\"");
} else {
Status ret = db.delete(table, tokens[1]);
System.out.println("Return result: " + ret.getName());
}
}
private static void handleInsert(String[] tokens, String table, DB db) {
if (tokens.length < 3) {
System.out.println("Error: syntax is \"insert keyname name1=value1 [name2=value2 ...]\"");
} else {
HashMap values = new HashMap<>();
for (int i = 2; i < tokens.length; i++) {
String[] nv = tokens[i].split("=");
values.put(nv[0], new StringByteIterator(nv[1]));
}
Status ret = db.insert(table, tokens[1], values);
System.out.println("Result: " + ret.getName());
}
}
private static void handleUpdate(String[] tokens, String table, DB db) {
if (tokens.length < 3) {
System.out.println("Error: syntax is \"update keyname name1=value1 [name2=value2 ...]\"");
} else {
HashMap values = new HashMap<>();
for (int i = 2; i < tokens.length; i++) {
String[] nv = tokens[i].split("=");
values.put(nv[0], new StringByteIterator(nv[1]));
}
Status ret = db.update(table, tokens[1], values);
System.out.println("Result: " + ret.getName());
}
}
private static void handleScan(String[] tokens, String table, DB db) {
if (tokens.length < 3) {
System.out.println("Error: syntax is \"scan keyname scanlength [field1 field2 ...]\"");
} else {
Set fields = null;
if (tokens.length > 3) {
fields = new HashSet<>();
fields.addAll(Arrays.asList(tokens).subList(3, tokens.length));
}
Vector> results = new Vector<>();
Status ret = db.scan(table, tokens[1], Integer.parseInt(tokens[2]), fields, results);
System.out.println("Result: " + ret.getName());
int record = 0;
if (results.isEmpty()) {
System.out.println("0 records");
} else {
System.out.println("--------------------------------");
}
- for (HashMap result : results) {
+ for (Map result : results) {
System.out.println("Record " + (record++));
for (Map.Entry ent : result.entrySet()) {
System.out.println(ent.getKey() + "=" + ent.getValue());
}
System.out.println("--------------------------------");
}
}
}
private static void handleRead(String[] tokens, String table, DB db) {
if (tokens.length == 1) {
System.out.println("Error: syntax is \"read keyname [field1 field2 ...]\"");
} else {
Set fields = null;
if (tokens.length > 2) {
fields = new HashSet<>();
fields.addAll(Arrays.asList(tokens).subList(2, tokens.length));
}
HashMap result = new HashMap<>();
Status ret = db.read(table, tokens[1], fields, result);
System.out.println("Return code: " + ret.getName());
for (Map.Entry ent : result.entrySet()) {
System.out.println(ent.getKey() + "=" + ent.getValue());
}
}
}
private static void handleTable(String[] tokens, String table) {
if (tokens.length == 1) {
System.out.println("Using table \"" + table + "\"");
} else if (tokens.length == 2) {
table = tokens[1];
System.out.println("Using table \"" + table + "\"");
} else {
System.out.println("Error: syntax is \"table tablename\"");
}
}
}
diff --git a/core/src/main/java/com/yahoo/ycsb/DB.java b/core/src/main/java/com/yahoo/ycsb/DB.java
index 2002474b..b93fd483 100644
--- a/core/src/main/java/com/yahoo/ycsb/DB.java
+++ b/core/src/main/java/com/yahoo/ycsb/DB.java
@@ -1,134 +1,135 @@
/**
* Copyright (c) 2010-2016 Yahoo! Inc., 2017 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;
import java.util.HashMap;
+import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Vector;
/**
* A layer for accessing a database to be benchmarked. Each thread in the client
* will be given its own instance of whatever DB class is to be used in the test.
* This class should be constructed using a no-argument constructor, so we can
* load it dynamically. Any argument-based initialization should be
* done by init().
*
* Note that YCSB does not make any use of the return codes returned by this class.
* Instead, it keeps a count of the return values and presents them to the user.
*
* The semantics of methods such as insert, update and delete vary from database
* to database. In particular, operations may or may not be durable once these
* methods commit, and some systems may return 'success' regardless of whether
* or not a tuple with a matching key existed before the call. Rather than dictate
* the exact semantics of these methods, we recommend you either implement them
* to match the database's default semantics, or the semantics of your
* target application. For the sake of comparison between experiments we also
* recommend you explain the semantics you chose when presenting performance results.
*/
public abstract class DB {
/**
* Properties for configuring this DB.
*/
private Properties properties = new Properties();
/**
* Set the properties for this DB.
*/
public void setProperties(Properties p) {
properties = p;
}
/**
* Get the set of properties for this DB.
*/
public Properties getProperties() {
return properties;
}
/**
* Initialize any state for this DB.
* Called once per DB instance; there is one DB instance per client thread.
*/
public void init() throws DBException {
}
/**
* Cleanup any state for this DB.
* Called once per DB instance; there is one DB instance per client thread.
*/
public void cleanup() throws DBException {
}
/**
* Read a record from the database. Each field/value pair from the result will be stored in a HashMap.
*
* @param table The name of the table
* @param key The record key of the record to read.
* @param fields The list of fields to read, or null for all of them
* @param result A HashMap of field/value pairs for the result
* @return The result of the operation.
*/
- public abstract Status read(String table, String key, Set fields, HashMap