From bc07237f62706b3f33a8b80d8d8217d53fdff4c7 Mon Sep 17 00:00:00 2001 From: nitsanw <nitsanw@yahoo.com> Date: Fri, 6 Mar 2015 09:25:24 +0100 Subject: [PATCH] [test] Add new mock DB simulator --- .../src/main/java/com/yahoo/ycsb/BasicDB.java | 9 +- .../java/com/yahoo/ycsb/GoodBadUglyDB.java | 162 ++++++++++++++++++ 2 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/com/yahoo/ycsb/GoodBadUglyDB.java diff --git a/core/src/main/java/com/yahoo/ycsb/BasicDB.java b/core/src/main/java/com/yahoo/ycsb/BasicDB.java index b34a7bce..0eff6f38 100644 --- a/core/src/main/java/com/yahoo/ycsb/BasicDB.java +++ b/core/src/main/java/com/yahoo/ycsb/BasicDB.java @@ -66,10 +66,11 @@ public class BasicDB extends DB delayNs = TimeUnit.MILLISECONDS.toNanos(todelay); } - long deadline = System.nanoTime() + delayNs; - do { - LockSupport.parkNanos(delayNs); - } while (System.nanoTime() < deadline && !Thread.interrupted()); + long now = System.nanoTime(); + final long deadline = now + delayNs; + do { + LockSupport.parkNanos(deadline - now); + } while ((now = System.nanoTime()) < deadline && !Thread.interrupted()); } } diff --git a/core/src/main/java/com/yahoo/ycsb/GoodBadUglyDB.java b/core/src/main/java/com/yahoo/ycsb/GoodBadUglyDB.java new file mode 100644 index 00000000..706438eb --- /dev/null +++ b/core/src/main/java/com/yahoo/ycsb/GoodBadUglyDB.java @@ -0,0 +1,162 @@ +/** + * 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 static java.util.concurrent.TimeUnit.MICROSECONDS; + +import java.util.HashMap; +import java.util.Random; +import java.util.Set; +import java.util.Vector; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.LockSupport; +import java.util.concurrent.locks.ReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; + +/** + * Basic DB that just prints out the requested operations, instead of doing them against a database. + */ +public class GoodBadUglyDB extends DB { + public static final String SIMULATE_DELAY = "gbudb.delays"; + public static final String SIMULATE_DELAY_DEFAULT = "200,1000,10000,50000,100000"; + long delays[]; + static ReadWriteLock DB_ACCESS = new ReentrantReadWriteLock(); + + public GoodBadUglyDB() { + delays = new long[] { 200, 1000, 10000, 50000, 200000 }; + } + + void delay() { + final Random random = Utils.random(); + double p = random.nextDouble(); + int mod; + if (p < 0.9) { + mod = 0; + } else if (p < 0.99) { + mod = 1; + } else if (p < 0.9999) { + mod = 2; + } else { + mod = 3; + } + // this will make mod 3 pauses global + Lock lock = mod == 3 ? DB_ACCESS.writeLock() : DB_ACCESS.readLock(); + if (mod == 3) { + System.out.println("OUCH"); + } + lock.lock(); + try { + final long baseDelayNs = MICROSECONDS.toNanos(delays[mod]); + final int delayRangeNs = (int) (MICROSECONDS.toNanos(delays[mod+1]) - baseDelayNs); + final long delayNs = baseDelayNs + random.nextInt(delayRangeNs); + long now = System.nanoTime(); + final long deadline = now + delayNs; + do { + LockSupport.parkNanos(deadline - now); + } while ((now = System.nanoTime()) < deadline && !Thread.interrupted()); + } + finally { + lock.unlock(); + } + + } + + /** + * Initialize any state for this DB. Called once per DB instance; there is one DB instance per client thread. + */ + public void init() { + int i=0; + for(String delay: getProperties().getProperty(SIMULATE_DELAY, SIMULATE_DELAY_DEFAULT).split(",")){ + delays[i++] = Long.parseLong(delay); + } + } + + /** + * 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 int read(String table, String key, Set<String> fields, HashMap<String, ByteIterator> result) { + delay(); + return 0; + } + + /** + * 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 int scan(String table, String startkey, int recordcount, Set<String> fields, + Vector<HashMap<String, ByteIterator>> result) { + delay(); + + return 0; + } + + /** + * 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 int update(String table, String key, HashMap<String, ByteIterator> values) { + delay(); + + return 0; + } + + /** + * 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 int insert(String table, String key, HashMap<String, ByteIterator> values) { + delay(); + return 0; + } + + /** + * 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 int delete(String table, String key) { + delay(); + return 0; + } +} -- GitLab