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