fields) {
+ final byte[][] qualifiers = new byte[fields.size()][];
+ int idx = 0;
+ for (final String field : fields) {
+ qualifiers[idx++] = field.getBytes();
+ }
+ return qualifiers;
+ }
+}
\ No newline at end of file
diff --git a/asynchbase/src/main/java/com/yahoo/ycsb/db/package-info.java b/asynchbase/src/main/java/com/yahoo/ycsb/db/package-info.java
new file mode 100644
index 00000000..72faa501
--- /dev/null
+++ b/asynchbase/src/main/java/com/yahoo/ycsb/db/package-info.java
@@ -0,0 +1,21 @@
+/**
+ * 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.
+ */
+
+/**
+ * The YCSB binding for HBase using the AsyncHBase client.
+ */
+package com.yahoo.ycsb.db;
diff --git a/asynchbase/src/test/java/com/google/common/base/Stopwatch.java b/asynchbase/src/test/java/com/google/common/base/Stopwatch.java
new file mode 100644
index 00000000..4d46924b
--- /dev/null
+++ b/asynchbase/src/test/java/com/google/common/base/Stopwatch.java
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2008 The Guava Authors
+ *
+ * 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.
+ */
+
+package com.google.common.base;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.concurrent.TimeUnit.MICROSECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * An object that measures elapsed time in nanoseconds. It is useful to measure
+ * elapsed time using this class instead of direct calls to {@link
+ * System#nanoTime} for a few reasons:
+ *
+ *
+ * An alternate time source can be substituted, for testing or performance
+ * reasons.
+ * As documented by {@code nanoTime}, the value returned has no absolute
+ * meaning, and can only be interpreted as relative to another timestamp
+ * returned by {@code nanoTime} at a different time. {@code Stopwatch} is a
+ * more effective abstraction because it exposes only these relative values,
+ * not the absolute ones.
+ *
+ *
+ * Basic usage:
+ *
+ * Stopwatch stopwatch = Stopwatch.{@link #createStarted createStarted}();
+ * doSomething();
+ * stopwatch.{@link #stop stop}(); // optional
+ *
+ * long millis = stopwatch.elapsed(MILLISECONDS);
+ *
+ * log.info("that took: " + stopwatch); // formatted string like "12.3 ms"
+ *
+ *
+ * Stopwatch methods are not idempotent; it is an error to start or stop a
+ * stopwatch that is already in the desired state.
+ *
+ *
When testing code that uses this class, use the {@linkplain
+ * #Stopwatch(Ticker) alternate constructor} to supply a fake or mock ticker.
+ * This allows you to
+ * simulate any valid behavior of the stopwatch.
+ *
+ *
Note: This class is not thread-safe.
+ *
+ * @author Kevin Bourrillion
+ * @since 10.0
+ */
+@Beta
+@GwtCompatible(emulated = true)
+public final class Stopwatch {
+ private final Ticker ticker;
+ private boolean isRunning;
+ private long elapsedNanos;
+ private long startTick;
+
+ /**
+ * Creates (but does not start) a new stopwatch using {@link System#nanoTime}
+ * as its time source.
+ *
+ * @since 15.0
+ */
+ public static Stopwatch createUnstarted() {
+ return new Stopwatch();
+ }
+
+ /**
+ * Creates (but does not start) a new stopwatch, using the specified time
+ * source.
+ *
+ * @since 15.0
+ */
+ public static Stopwatch createUnstarted(Ticker ticker) {
+ return new Stopwatch(ticker);
+ }
+
+ /**
+ * Creates (and starts) a new stopwatch using {@link System#nanoTime}
+ * as its time source.
+ *
+ * @since 15.0
+ */
+ public static Stopwatch createStarted() {
+ return new Stopwatch().start();
+ }
+
+ /**
+ * Creates (and starts) a new stopwatch, using the specified time
+ * source.
+ *
+ * @since 15.0
+ */
+ public static Stopwatch createStarted(Ticker ticker) {
+ return new Stopwatch(ticker).start();
+ }
+
+ /**
+ * Creates (but does not start) a new stopwatch using {@link System#nanoTime}
+ * as its time source.
+ *
+ * @deprecated Use {@link Stopwatch#createUnstarted()} instead.
+ */
+ @Deprecated
+ public Stopwatch() {
+ this(Ticker.systemTicker());
+ }
+
+ /**
+ * Creates (but does not start) a new stopwatch, using the specified time
+ * source.
+ *
+ * @deprecated Use {@link Stopwatch#createUnstarted(Ticker)} instead.
+ */
+ @Deprecated
+ public Stopwatch(Ticker ticker) {
+ this.ticker = checkNotNull(ticker, "ticker");
+ }
+
+ /**
+ * Returns {@code true} if {@link #start()} has been called on this stopwatch,
+ * and {@link #stop()} has not been called since the last call to {@code
+ * start()}.
+ */
+ public boolean isRunning() {
+ return isRunning;
+ }
+
+ /**
+ * Starts the stopwatch.
+ *
+ * @return this {@code Stopwatch} instance
+ * @throws IllegalStateException if the stopwatch is already running.
+ */
+ public Stopwatch start() {
+ checkState(!isRunning, "This stopwatch is already running.");
+ isRunning = true;
+ startTick = ticker.read();
+ return this;
+ }
+
+ /**
+ * Stops the stopwatch. Future reads will return the fixed duration that had
+ * elapsed up to this point.
+ *
+ * @return this {@code Stopwatch} instance
+ * @throws IllegalStateException if the stopwatch is already stopped.
+ */
+ public Stopwatch stop() {
+ long tick = ticker.read();
+ checkState(isRunning, "This stopwatch is already stopped.");
+ isRunning = false;
+ elapsedNanos += tick - startTick;
+ return this;
+ }
+
+ /**
+ * Sets the elapsed time for this stopwatch to zero,
+ * and places it in a stopped state.
+ *
+ * @return this {@code Stopwatch} instance
+ */
+ public Stopwatch reset() {
+ elapsedNanos = 0;
+ isRunning = false;
+ return this;
+ }
+
+ private long elapsedNanos() {
+ return isRunning ? ticker.read() - startTick + elapsedNanos : elapsedNanos;
+ }
+
+ /**
+ * Returns the current elapsed time shown on this stopwatch, expressed
+ * in the desired time unit, with any fraction rounded down.
+ *
+ *
Note that the overhead of measurement can be more than a microsecond, so
+ * it is generally not useful to specify {@link TimeUnit#NANOSECONDS}
+ * precision here.
+ *
+ * @since 14.0 (since 10.0 as {@code elapsedTime()})
+ */
+ public long elapsed(TimeUnit desiredUnit) {
+ return desiredUnit.convert(elapsedNanos(), NANOSECONDS);
+ }
+
+ /**
+ * Returns the current elapsed time shown on this stopwatch, expressed
+ * in the desired time unit, with any fraction rounded down.
+ *
+ *
Note that the overhead of measurement can be more than a microsecond, so
+ * it is generally not useful to specify {@link TimeUnit#NANOSECONDS}
+ * precision here.
+ *
+ * @deprecated Use {@link Stopwatch#elapsed(TimeUnit)} instead. This method is
+ * scheduled to be removed in Guava release 16.0.
+ */
+ @Deprecated
+ public long elapsedTime(TimeUnit desiredUnit) {
+ return elapsed(desiredUnit);
+ }
+
+ /**
+ * Returns the current elapsed time shown on this stopwatch, expressed
+ * in milliseconds, with any fraction rounded down. This is identical to
+ * {@code elapsed(TimeUnit.MILLISECONDS)}.
+ *
+ * @deprecated Use {@code stopwatch.elapsed(MILLISECONDS)} instead. This
+ * method is scheduled to be removed in Guava release 16.0.
+ */
+ @Deprecated
+ public long elapsedMillis() {
+ return elapsed(MILLISECONDS);
+ }
+
+ /**
+ * Returns a string representation of the current elapsed time.
+ */
+ @GwtIncompatible("String.format()")
+ @Override public String toString() {
+ long nanos = elapsedNanos();
+
+ TimeUnit unit = chooseUnit(nanos);
+ double value = (double) nanos / NANOSECONDS.convert(1, unit);
+
+ // Too bad this functionality is not exposed as a regular method call
+ return String.format("%.4g %s", value, abbreviate(unit));
+ }
+
+ private static TimeUnit chooseUnit(long nanos) {
+ if (SECONDS.convert(nanos, NANOSECONDS) > 0) {
+ return SECONDS;
+ }
+ if (MILLISECONDS.convert(nanos, NANOSECONDS) > 0) {
+ return MILLISECONDS;
+ }
+ if (MICROSECONDS.convert(nanos, NANOSECONDS) > 0) {
+ return MICROSECONDS;
+ }
+ return NANOSECONDS;
+ }
+
+ private static String abbreviate(TimeUnit unit) {
+ switch (unit) {
+ case NANOSECONDS:
+ return "ns";
+ case MICROSECONDS:
+ return "\u03bcs"; // μs
+ case MILLISECONDS:
+ return "ms";
+ case SECONDS:
+ return "s";
+ default:
+ throw new AssertionError();
+ }
+ }
+}
\ No newline at end of file
diff --git a/asynchbase/src/test/java/com/google/common/io/Closeables.java b/asynchbase/src/test/java/com/google/common/io/Closeables.java
new file mode 100644
index 00000000..4a92c9c0
--- /dev/null
+++ b/asynchbase/src/test/java/com/google/common/io/Closeables.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * 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.
+ */
+
+package com.google.common.io;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.VisibleForTesting;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.annotation.Nullable;
+
+/**
+ * Utility methods for working with {@link Closeable} objects.
+ *
+ * @author Michael Lancaster
+ * @since 1.0
+ */
+@Beta
+public final class Closeables {
+ @VisibleForTesting static final Logger logger
+ = Logger.getLogger(Closeables.class.getName());
+
+ private Closeables() {}
+
+ /**
+ * Closes a {@link Closeable}, with control over whether an
+ * {@code IOException} may be thrown. This is primarily useful in a
+ * finally block, where a thrown exception needs to be logged but not
+ * propagated (otherwise the original exception will be lost).
+ *
+ *
If {@code swallowIOException} is true then we never throw
+ * {@code IOException} but merely log it.
+ *
+ *
Example:
+ *
+ *
public void useStreamNicely() throws IOException {
+ * SomeStream stream = new SomeStream("foo");
+ * boolean threw = true;
+ * try {
+ * // Some code which does something with the Stream. May throw a
+ * // Throwable.
+ * threw = false; // No throwable thrown.
+ * } finally {
+ * // Close the stream.
+ * // If an exception occurs, only rethrow it if (threw==false).
+ * Closeables.close(stream, threw);
+ * }
+ *
+ *
+ * @param closeable the {@code Closeable} object to be closed, or null,
+ * in which case this method does nothing
+ * @param swallowIOException if true, don't propagate IO exceptions
+ * thrown by the {@code close} methods
+ * @throws IOException if {@code swallowIOException} is false and
+ * {@code close} throws an {@code IOException}.
+ */
+ public static void close(@Nullable Closeable closeable,
+ boolean swallowIOException) throws IOException {
+ if (closeable == null) {
+ return;
+ }
+ try {
+ closeable.close();
+ } catch (IOException e) {
+ if (swallowIOException) {
+ logger.log(Level.WARNING,
+ "IOException thrown while closing Closeable.", e);
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ /**
+ * Equivalent to calling {@code close(closeable, true)}, but with no
+ * IOException in the signature.
+ * @param closeable the {@code Closeable} object to be closed, or null, in
+ * which case this method does nothing
+ */
+ public static void closeQuietly(@Nullable Closeable closeable) {
+ try {
+ close(closeable, true);
+ } catch (IOException e) {
+ logger.log(Level.SEVERE, "IOException should not have been thrown.", e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/asynchbase/src/test/java/com/google/common/io/LimitInputStream.java b/asynchbase/src/test/java/com/google/common/io/LimitInputStream.java
new file mode 100644
index 00000000..a529f5e1
--- /dev/null
+++ b/asynchbase/src/test/java/com/google/common/io/LimitInputStream.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2007 The Guava Authors
+ *
+ * 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.
+ */
+
+package com.google.common.io;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * An InputStream that limits the number of bytes which can be read.
+ *
+ * @author Charles Fry
+ * @since 1.0
+ */
+@Beta
+public final class LimitInputStream extends FilterInputStream {
+
+ private long left;
+ private long mark = -1;
+
+ /**
+ * Wraps another input stream, limiting the number of bytes which can be read.
+ *
+ * @param in the input stream to be wrapped
+ * @param limit the maximum number of bytes to be read
+ */
+ public LimitInputStream(InputStream in, long limit) {
+ super(in);
+ Preconditions.checkNotNull(in);
+ Preconditions.checkArgument(limit >= 0, "limit must be non-negative");
+ left = limit;
+ }
+
+ @Override public int available() throws IOException {
+ return (int) Math.min(in.available(), left);
+ }
+
+ @Override public synchronized void mark(int readlimit) {
+ in.mark(readlimit);
+ mark = left;
+ // it's okay to mark even if mark isn't supported, as reset won't work
+ }
+
+ @Override public int read() throws IOException {
+ if (left == 0) {
+ return -1;
+ }
+
+ int result = in.read();
+ if (result != -1) {
+ --left;
+ }
+ return result;
+ }
+
+ @Override public int read(byte[] b, int off, int len) throws IOException {
+ if (left == 0) {
+ return -1;
+ }
+
+ len = (int) Math.min(len, left);
+ int result = in.read(b, off, len);
+ if (result != -1) {
+ left -= result;
+ }
+ return result;
+ }
+
+ @Override public synchronized void reset() throws IOException {
+ if (!in.markSupported()) {
+ throw new IOException("Mark not supported");
+ }
+ if (mark == -1) {
+ throw new IOException("Mark not set");
+ }
+
+ in.reset();
+ left = mark;
+ }
+
+ @Override public long skip(long n) throws IOException {
+ n = Math.min(n, left);
+ long skipped = in.skip(n);
+ left -= skipped;
+ return skipped;
+ }
+}
\ No newline at end of file
diff --git a/asynchbase/src/test/java/com/yahoo/ycsb/db/AsyncHBaseTest.java b/asynchbase/src/test/java/com/yahoo/ycsb/db/AsyncHBaseTest.java
new file mode 100644
index 00000000..29a09a79
--- /dev/null
+++ b/asynchbase/src/test/java/com/yahoo/ycsb/db/AsyncHBaseTest.java
@@ -0,0 +1,211 @@
+/**
+ * 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.db;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.junit.Assume.assumeTrue;
+
+import com.yahoo.ycsb.ByteIterator;
+import com.yahoo.ycsb.Status;
+import com.yahoo.ycsb.StringByteIterator;
+import com.yahoo.ycsb.db.AsyncHBaseClient;
+import com.yahoo.ycsb.measurements.Measurements;
+import com.yahoo.ycsb.workloads.CoreWorkload;
+
+import org.apache.hadoop.hbase.HBaseTestingUtility;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.client.Get;
+import org.apache.hadoop.hbase.client.Put;
+import org.apache.hadoop.hbase.client.Result;
+import org.apache.hadoop.hbase.client.Table;
+import org.apache.hadoop.hbase.util.Bytes;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Properties;
+import java.util.Vector;
+
+/**
+ * Integration tests for the YCSB AsyncHBase client, using an HBase minicluster.
+ * These are the same as those for the hbase10 client.
+ */
+public class AsyncHBaseTest {
+
+ private final static String COLUMN_FAMILY = "cf";
+
+ private static HBaseTestingUtility testingUtil;
+ private AsyncHBaseClient client;
+ private Table table = null;
+
+ private static boolean isWindows() {
+ final String os = System.getProperty("os.name");
+ return os.startsWith("Windows");
+ }
+
+ /**
+ * Creates a mini-cluster for use in these tests.
+ *
+ * This is a heavy-weight operation, so invoked only once for the test class.
+ */
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ // Minicluster setup fails on Windows with an UnsatisfiedLinkError.
+ // Skip if windows.
+ assumeTrue(!isWindows());
+ testingUtil = HBaseTestingUtility.createLocalHTU();
+ testingUtil.startMiniCluster();
+ }
+
+ /**
+ * Tears down mini-cluster.
+ */
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ if (testingUtil != null) {
+ testingUtil.shutdownMiniCluster();
+ }
+ }
+
+ /**
+ * Sets up the mini-cluster for testing.
+ *
+ * We re-create the table for each test.
+ */
+ @Before
+ public void setUp() throws Exception {
+ Properties p = new Properties();
+ p.setProperty("columnfamily", COLUMN_FAMILY);
+
+ Measurements.setProperties(p);
+ final CoreWorkload workload = new CoreWorkload();
+ workload.init(p);
+
+ table = testingUtil.createTable(TableName.valueOf(CoreWorkload.table), Bytes.toBytes(COLUMN_FAMILY));
+
+ final String zkQuorum = "127.0.0.1:" + testingUtil.getZkCluster().getClientPort();
+ p.setProperty("hbase.zookeeper.quorum", zkQuorum);
+ client = new AsyncHBaseClient();
+ client.setProperties(p);
+ client.init();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ table.close();
+ testingUtil.deleteTable(CoreWorkload.table);
+ }
+
+ @Test
+ public void testRead() throws Exception {
+ final String rowKey = "row1";
+ final Put p = new Put(Bytes.toBytes(rowKey));
+ p.addColumn(Bytes.toBytes(COLUMN_FAMILY),
+ Bytes.toBytes("column1"), Bytes.toBytes("value1"));
+ p.addColumn(Bytes.toBytes(COLUMN_FAMILY),
+ Bytes.toBytes("column2"), Bytes.toBytes("value2"));
+ table.put(p);
+
+ final HashMap result = new HashMap();
+ final Status status = client.read(CoreWorkload.table, rowKey, null, result);
+ assertEquals(Status.OK, status);
+ assertEquals(2, result.size());
+ assertEquals("value1", result.get("column1").toString());
+ assertEquals("value2", result.get("column2").toString());
+ }
+
+ @Test
+ public void testReadMissingRow() throws Exception {
+ final HashMap result = new HashMap();
+ final Status status = client.read(CoreWorkload.table, "Missing row", null, result);
+ assertEquals(Status.NOT_FOUND, status);
+ assertEquals(0, result.size());
+ }
+
+ @Test
+ public void testScan() throws Exception {
+ // Fill with data
+ final String colStr = "row_number";
+ final byte[] col = Bytes.toBytes(colStr);
+ final int n = 10;
+ final List puts = new ArrayList(n);
+ for(int i = 0; i < n; i++) {
+ final byte[] key = Bytes.toBytes(String.format("%05d", i));
+ final byte[] value = java.nio.ByteBuffer.allocate(4).putInt(i).array();
+ final Put p = new Put(key);
+ p.addColumn(Bytes.toBytes(COLUMN_FAMILY), col, value);
+ puts.add(p);
+ }
+ table.put(puts);
+
+ // Test
+ final Vector> result =
+ new Vector>();
+
+ // Scan 5 records, skipping the first
+ client.scan(CoreWorkload.table, "00001", 5, null, result);
+
+ assertEquals(5, result.size());
+ for(int i = 0; i < 5; i++) {
+ final HashMap row = result.get(i);
+ assertEquals(1, row.size());
+ assertTrue(row.containsKey(colStr));
+ final byte[] bytes = row.get(colStr).toArray();
+ final ByteBuffer buf = ByteBuffer.wrap(bytes);
+ final int rowNum = buf.getInt();
+ assertEquals(i + 1, rowNum);
+ }
+ }
+
+ @Test
+ public void testUpdate() throws Exception{
+ final String key = "key";
+ final HashMap input = new HashMap();
+ input.put("column1", "value1");
+ input.put("column2", "value2");
+ final Status status = client.insert(CoreWorkload.table, key, StringByteIterator.getByteIteratorMap(input));
+ assertEquals(Status.OK, status);
+
+ // Verify result
+ final Get get = new Get(Bytes.toBytes(key));
+ final Result result = this.table.get(get);
+ assertFalse(result.isEmpty());
+ assertEquals(2, result.size());
+ for(final java.util.Map.Entry entry : input.entrySet()) {
+ assertEquals(entry.getValue(),
+ new String(result.getValue(Bytes.toBytes(COLUMN_FAMILY),
+ Bytes.toBytes(entry.getKey()))));
+ }
+ }
+
+ @Test
+ @Ignore("Not yet implemented")
+ public void testDelete() {
+ fail("Not yet implemented");
+ }
+}
+
diff --git a/asynchbase/src/test/resources/hbase-site.xml b/asynchbase/src/test/resources/hbase-site.xml
new file mode 100644
index 00000000..a8b29e45
--- /dev/null
+++ b/asynchbase/src/test/resources/hbase-site.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+ hbase.master.info.port
+ -1
+ The port for the hbase master web UI
+ Set to -1 if you do not want the info server to run.
+
+
+
+ hbase.regionserver.info.port
+ -1
+ The port for the hbase regionserver web UI
+ Set to -1 if you do not want the info server to run.
+
+
+
diff --git a/asynchbase/src/test/resources/log4j.properties b/asynchbase/src/test/resources/log4j.properties
new file mode 100644
index 00000000..a9df32e0
--- /dev/null
+++ b/asynchbase/src/test/resources/log4j.properties
@@ -0,0 +1,28 @@
+#
+# Copyright (c) 2015 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.
+#
+
+# Root logger option
+log4j.rootLogger=WARN, stderr
+
+log4j.appender.stderr=org.apache.log4j.ConsoleAppender
+log4j.appender.stderr.target=System.err
+log4j.appender.stderr.layout=org.apache.log4j.PatternLayout
+log4j.appender.stderr.layout.conversionPattern=%d{yyyy/MM/dd HH:mm:ss} %-5p %c %x - %m%n
+
+# Suppress messages from ZKTableStateManager: Creates a large number of table
+# state change messages.
+log4j.logger.org.apache.hadoop.hbase.zookeeper.ZKTableStateManager=ERROR
diff --git a/bin/ycsb b/bin/ycsb
index de2cdfd3..e85ca43d 100755
--- a/bin/ycsb
+++ b/bin/ycsb
@@ -1,262 +1,263 @@
#!/usr/bin/env python
#
# Copyright (c) 2012 - 2015 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.
#
import errno
import fnmatch
import io
import os
import shlex
import sys
import subprocess
try:
import argparse
except ImportError:
print >> sys.stderr, '[ERROR] argparse not found. Try installing it via "pip".'
raise
BASE_URL = "https://github.com/brianfrankcooper/YCSB/tree/master/"
COMMANDS = {
"shell" : {
"command" : "",
"description" : "Interactive mode",
"main" : "com.yahoo.ycsb.CommandLine",
},
"load" : {
"command" : "-load",
"description" : "Execute the load phase",
"main" : "com.yahoo.ycsb.Client",
},
"run" : {
"command" : "-t",
"description" : "Execute the transaction phase",
"main" : "com.yahoo.ycsb.Client",
},
}
DATABASES = {
"accumulo" : "com.yahoo.ycsb.db.accumulo.AccumuloClient",
"aerospike" : "com.yahoo.ycsb.db.AerospikeClient",
+ "asynchbase" : "com.yahoo.ycsb.db.AsyncHBaseClient",
"basic" : "com.yahoo.ycsb.BasicDB",
"cassandra-7" : "com.yahoo.ycsb.db.CassandraClient7",
"cassandra-8" : "com.yahoo.ycsb.db.CassandraClient8",
"cassandra-10" : "com.yahoo.ycsb.db.CassandraClient10",
"cassandra-cql": "com.yahoo.ycsb.db.CassandraCQLClient",
"cassandra2-cql": "com.yahoo.ycsb.db.CassandraCQLClient",
"couchbase" : "com.yahoo.ycsb.db.CouchbaseClient",
"couchbase2" : "com.yahoo.ycsb.db.couchbase2.Couchbase2Client",
"dynamodb" : "com.yahoo.ycsb.db.DynamoDBClient",
"elasticsearch": "com.yahoo.ycsb.db.ElasticsearchClient",
"geode" : "com.yahoo.ycsb.db.GeodeClient",
"googlebigtable" : "com.yahoo.ycsb.db.GoogleBigtableClient",
"googledatastore" : "com.yahoo.ycsb.db.GoogleDatastoreClient",
"hbase094" : "com.yahoo.ycsb.db.HBaseClient",
"hbase098" : "com.yahoo.ycsb.db.HBaseClient",
"hbase10" : "com.yahoo.ycsb.db.HBaseClient10",
"hypertable" : "com.yahoo.ycsb.db.HypertableClient",
"infinispan-cs": "com.yahoo.ycsb.db.InfinispanRemoteClient",
"infinispan" : "com.yahoo.ycsb.db.InfinispanClient",
"jdbc" : "com.yahoo.ycsb.db.JdbcDBClient",
"kudu" : "com.yahoo.ycsb.db.KuduYCSBClient",
"mapkeeper" : "com.yahoo.ycsb.db.MapKeeperClient",
"memcached" : "com.yahoo.ycsb.db.MemcachedClient",
"mongodb" : "com.yahoo.ycsb.db.MongoDbClient",
"mongodb-async": "com.yahoo.ycsb.db.AsyncMongoDbClient",
"nosqldb" : "com.yahoo.ycsb.db.NoSqlDbClient",
"orientdb" : "com.yahoo.ycsb.db.OrientDBClient",
"redis" : "com.yahoo.ycsb.db.RedisClient",
"riak" : "com.yahoo.ycsb.db.riak.RiakKVClient",
"s3" : "com.yahoo.ycsb.db.S3Client",
"solr" : "com.yahoo.ycsb.db.SolrClient",
"tarantool" : "com.yahoo.ycsb.db.TarantoolClient",
"voldemort" : "com.yahoo.ycsb.db.VoldemortClient"
}
OPTIONS = {
"-P file" : "Specify workload file",
"-p key=value" : "Override workload property",
"-s" : "Print status to stderr",
"-target n" : "Target ops/sec (default: unthrottled)",
"-threads n" : "Number of client threads (default: 1)",
"-cp path" : "Additional Java classpath entries",
"-jvm-args args" : "Additional arguments to the JVM",
}
def usage():
output = io.BytesIO()
print >> output, "%s command database [options]" % sys.argv[0]
print >> output, "\nCommands:"
for command in sorted(COMMANDS.keys()):
print >> output, " %s %s" % (command.ljust(14),
COMMANDS[command]["description"])
print >> output, "\nDatabases:"
for db in sorted(DATABASES.keys()):
print >> output, " %s %s" % (db.ljust(14), BASE_URL +
db.split("-")[0])
print >> output, "\nOptions:"
for option in sorted(OPTIONS.keys()):
print >> output, " %s %s" % (option.ljust(14), OPTIONS[option])
print >> output, """\nWorkload Files:
There are various predefined workloads under workloads/ directory.
See https://github.com/brianfrankcooper/YCSB/wiki/Core-Properties
for the list of workload properties."""
return output.getvalue()
def check_output(cmd):
p = subprocess.Popen(cmd, stdout=subprocess.PIPE)
stdout, _ = p.communicate()
if p.returncode:
raise subprocess.CalledProcessError(p.returncode, cmd)
return stdout
def debug(message):
print >> sys.stderr, "[DEBUG] ", message
def warn(message):
print >> sys.stderr, "[WARN] ", message
def error(message):
print >> sys.stderr, "[ERROR] ", message
def find_jars(dir, glob='*.jar'):
jars = []
for (dirpath, dirnames, filenames) in os.walk(dir):
for filename in fnmatch.filter(filenames, glob):
jars.append(os.path.join(dirpath, filename))
return jars
def get_ycsb_home():
dir = os.path.abspath(os.path.dirname(sys.argv[0]))
while "LICENSE.txt" not in os.listdir(dir):
dir = os.path.join(dir, os.path.pardir)
return os.path.abspath(dir)
def is_distribution():
# If there's a top level pom, we're a source checkout. otherwise a dist artifact
return "pom.xml" not in os.listdir(get_ycsb_home())
# Run the maven dependency plugin to get the local jar paths.
# presumes maven can run, so should only be run on source checkouts
# will invoke the 'package' goal for the given binding in order to resolve intra-project deps
# presumes maven properly handles system-specific path separators
# Given module is full module name eg. 'core' or 'couchbase-binding'
def get_classpath_from_maven(module):
try:
debug("Running 'mvn -pl com.yahoo.ycsb:" + module + " -am package -DskipTests "
"dependency:build-classpath -DincludeScope=compile -Dmdep.outputFilterFile=true'")
mvn_output = check_output(["mvn", "-pl", "com.yahoo.ycsb:" + module,
"-am", "package", "-DskipTests",
"dependency:build-classpath",
"-DincludeScope=compile",
"-Dmdep.outputFilterFile=true"])
# the above outputs a "classpath=/path/tojar:/path/to/other/jar" for each module
# the last module will be the datastore binding
line = [x for x in mvn_output.splitlines() if x.startswith("classpath=")][-1:]
return line[0][len("classpath="):]
except subprocess.CalledProcessError, err:
error("Attempting to generate a classpath from Maven failed "
"with return code '" + str(err.returncode) + "'. The output from "
"Maven follows, try running "
"'mvn -DskipTests package dependency:build=classpath' on your "
"own and correct errors." + os.linesep + os.linesep + "mvn output:" + os.linesep
+ err.output)
sys.exit(err.returncode)
def main():
p = argparse.ArgumentParser(
usage=usage(),
formatter_class=argparse.RawDescriptionHelpFormatter)
p.add_argument('-cp', dest='classpath', help="""Additional classpath
entries, e.g. '-cp /tmp/hbase-1.0.1.1/conf'. Will be
prepended to the YCSB classpath.""")
p.add_argument("-jvm-args", default=[], type=shlex.split,
help="""Additional arguments to pass to 'java', e.g.
'-Xmx4g'""")
p.add_argument("command", choices=sorted(COMMANDS),
help="""Command to run.""")
p.add_argument("database", choices=sorted(DATABASES),
help="""Database to test.""")
args, remaining = p.parse_known_args()
ycsb_home = get_ycsb_home()
# Use JAVA_HOME to find java binary if set, otherwise just use PATH.
java = "java"
java_home = os.getenv("JAVA_HOME")
if java_home:
java = os.path.join(java_home, "bin", "java")
db_classname = DATABASES[args.database]
command = COMMANDS[args.command]["command"]
main_classname = COMMANDS[args.command]["main"]
# Classpath set up
binding = args.database.split("-")[0]
# Deprecation message for the entire cassandra-binding
if binding == "cassandra":
warn("The 'cassandra-7', 'cassandra-8', 'cassandra-10', and "
"cassandra-cql' clients are deprecated. If you are using "
"Cassandra 2.X try using the 'cassandra2-cql' client instead.")
if is_distribution():
db_dir = os.path.join(ycsb_home, binding + "-binding")
# include top-level conf for when we're a binding-specific artifact.
# If we add top-level conf to the general artifact, starting here
# will allow binding-specific conf to override (because it's prepended)
cp = [os.path.join(ycsb_home, "conf")]
cp.extend(find_jars(os.path.join(ycsb_home, "lib")))
cp.extend(find_jars(os.path.join(db_dir, "lib")))
else:
warn("Running against a source checkout. In order to get our runtime "
"dependencies we'll have to invoke Maven. Depending on the state "
"of your system, this may take ~30-45 seconds")
db_location = "core" if binding == "basic" else binding
project = "core" if binding == "basic" else binding + "-binding"
db_dir = os.path.join(ycsb_home, db_location)
# goes first so we can rely on side-effect of package
maven_says = get_classpath_from_maven(project)
# TODO when we have a version property, skip the glob
cp = find_jars(os.path.join(db_dir, "target"),
project + "*.jar")
# alredy in jar:jar:jar form
cp.append(maven_says)
cp.insert(0, os.path.join(db_dir, "conf"))
classpath = os.pathsep.join(cp)
if args.classpath:
classpath = os.pathsep.join([args.classpath, classpath])
ycsb_command = ([java] + args.jvm_args +
["-cp", classpath,
main_classname, "-db", db_classname] + remaining)
if command:
ycsb_command.append(command)
print >> sys.stderr, " ".join(ycsb_command)
try:
return subprocess.call(ycsb_command)
except OSError as e:
if e.errno == errno.ENOENT:
error('Command failed. Is java installed and on your PATH?')
return 1
else:
raise
if __name__ == '__main__':
sys.exit(main())
diff --git a/distribution/pom.xml b/distribution/pom.xml
index 6dc972f6..459b4db3 100644
--- a/distribution/pom.xml
+++ b/distribution/pom.xml
@@ -1,207 +1,212 @@
4.0.0
com.yahoo.ycsb
root
0.9.0-SNAPSHOT
ycsb
YCSB Release Distribution Builder
pom
This module creates the release package of the YCSB with all DB library bindings.
It is only used by the build process and does not contain any real
code of itself.
com.yahoo.ycsb
core
${project.version}
com.yahoo.ycsb
accumulo-binding
${project.version}
com.yahoo.ycsb
aerospike-binding
${project.version}
+
+ com.yahoo.ycsb
+ asynchbase-binding
+ ${project.version}
+
com.yahoo.ycsb
cassandra-binding
${project.version}
com.yahoo.ycsb
couchbase-binding
${project.version}
com.yahoo.ycsb
couchbase2-binding
${project.version}
com.yahoo.ycsb
dynamodb-binding
${project.version}
com.yahoo.ycsb
elasticsearch-binding
${project.version}
com.yahoo.ycsb
geode-binding
${project.version}
com.yahoo.ycsb
googledatastore-binding
${project.version}
com.yahoo.ycsb
googlebigtable-binding
${project.version}
com.yahoo.ycsb
hbase094-binding
${project.version}
com.yahoo.ycsb
hbase098-binding
${project.version}
com.yahoo.ycsb
hbase10-binding
${project.version}
com.yahoo.ycsb
hypertable-binding
${project.version}
com.yahoo.ycsb
infinispan-binding
${project.version}
com.yahoo.ycsb
jdbc-binding
${project.version}
com.yahoo.ycsb
kudu-binding
${project.version}
com.yahoo.ycsb
memcached-binding
${project.version}
com.yahoo.ycsb
mongodb-binding
${project.version}
com.yahoo.ycsb
nosqldb-binding
${project.version}
com.yahoo.ycsb
orientdb-binding
${project.version}
com.yahoo.ycsb
redis-binding
${project.version}
com.yahoo.ycsb
riak-binding
${project.version}
com.yahoo.ycsb
s3-binding
${project.version}
com.yahoo.ycsb
solr-binding
${project.version}
com.yahoo.ycsb
tarantool-binding
${project.version}
org.apache.maven.plugins
maven-assembly-plugin
${maven.assembly.version}
src/main/assembly/distribution.xml
false
posix
package
single
diff --git a/pom.xml b/pom.xml
index 71bdc2b7..d0028c8f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,176 +1,178 @@
4.0.0
com.yahoo.ycsb
root
0.9.0-SNAPSHOT
pom
YCSB Root
This is the top level project that builds, packages the core and all the DB bindings for YCSB infrastructure.
scm:git:git://github.com/brianfrankcooper/YCSB.git
master
https://github.com/brianfrankcooper/YCSB
checkstyle
checkstyle
5.0
org.jdom
jdom
1.1
com.google.collections
google-collections
1.0
org.slf4j
slf4j-api
1.6.4
2.5.5
2.10
+ 1.7.1
0.94.27
0.98.14-hadoop2
1.0.2
1.6.0
1.2.9
1.0.3
3.0.0
1.0.0-incubating.M1
0.2.3
7.2.2.Final
0.6.0
2.1.1
3.0.3
2.0.1
2.1.8
2.0.0
1.10.20
0.81
UTF-8
0.8.0
0.9.5.6
1.4.10
2.2.6
1.6.5
2.0.5
3.1.2
5.4.0
core
binding-parent
accumulo
aerospike
+ asynchbase
cassandra
cassandra2
couchbase
couchbase2
distribution
dynamodb
elasticsearch
geode
googlebigtable
googledatastore
hbase094
hbase098
hbase10
hypertable
infinispan
jdbc
kudu
memcached
mongodb
nosqldb
orientdb
redis
riak
s3
solr
tarantool
org.apache.maven.plugins
maven-checkstyle-plugin
2.15
org.apache.maven.plugins
maven-compiler-plugin
3.3
1.7
1.7
org.apache.maven.plugins
maven-checkstyle-plugin
validate
validate
check
checkstyle.xml