Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don’t worry, you can still create the pull request.
  • 4 commits
  • 7 files changed
  • 0 commit comments
  • 1 contributor
View
4 .gitignore
@@ -8,3 +8,7 @@ output*
.project
.classpath
.settings
+
+
+**/*.iml
+.idea/
View
67 README.md
@@ -1,38 +1,29 @@
-Yahoo! Cloud System Benchmark (YCSB)
-====================================
-[![Build Status](https://travis-ci.org/brianfrankcooper/YCSB.png?branch=master)](https://travis-ci.org/brianfrankcooper/YCSB)
-
-Links
------
-http://wiki.github.com/brianfrankcooper/YCSB/
-http://research.yahoo.com/Web_Information_Management/YCSB/
-ycsb-users@yahoogroups.com
-
-Getting Started
----------------
-
-1. Download the latest release of YCSB:
-
- ```sh
- wget https://github.com/downloads/brianfrankcooper/YCSB/ycsb-0.1.4.tar.gz
- tar xfvz ycsb-0.1.4
- cd ycsb-0.1.4
- ```
-
-2. Set up a database to benchmark. There is a README file under each binding
- directory.
-
-3. Run YCSB command.
-
- ```sh
- bin/ycsb load basic -P workloads/workloada
- bin/ycsb run basic -P workloads/workloada
- ```
-
- Running the `ycsb` command without any argument will print the usage.
-
- See https://github.com/brianfrankcooper/YCSB/wiki/Running-a-Workload
- for a detailed documentation on how to run a workload.
-
- See https://github.com/brianfrankcooper/YCSB/wiki/Core-Properties for
- the list of available workload properties.
+# Couchbase YCSB Fork
+
+**Note that this fork fixes the coordinate omission problems and represents more realistic results. Only compare
+results that are run with the same harness, not to YCSB results which do not have the coordinated omission fixes
+in place.**
+
+## Quick Start
+
+This is the Couchbase fork of the YCSB framework. It contains modules for both the 1.4 and 2.1 Java SDK, which can
+be used through the `couchbase-1` and `couchbase-2` targets.
+
+For example:
+
+```
+./bin/ycsb run couchbase-1 -P workloads/workloadb
+```
+
+```
+./bin/ycsb run couchbase-2 -P workloads/workloadb
+```
+
+## Properties
+You can use the following properties across the old and new SDK:
+
+- `couchbase.host` => `127.0.0.1`
+- `couchbase.bucket` => `default`
+- `couchbase.password` => ``
+- `couchbase.persistTo` => `0` (0, 1, 2, 3, 4 or master)
+- `couchbase.replicateTo` => `0` (0, 1, 2 or 3)
View
4 bin/ycsb
@@ -41,7 +41,9 @@ DATABASES = {
"nosqldb" : "com.yahoo.ycsb.db.NoSqlDbClient",
"orientdb" : "com.yahoo.ycsb.db.OrientDBClient",
"redis" : "com.yahoo.ycsb.db.RedisClient",
- "voldemort" : "com.yahoo.ycsb.db.VoldemortClient",
+ "voldemort" : "com.yahoo.ycsb.db.VoldemortClient",
+ "couchbase-2" : "com.yahoo.ycsb.db.Couchbase2Client",
+ "couchbase-1" : "com.yahoo.ycsb.db.Couchbase1Client"
}
OPTIONS = {
View
61 couchbase/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.yahoo.ycsb</groupId>
+ <artifactId>root</artifactId>
+ <version>0.1.4</version>
+ </parent>
+
+ <artifactId>couchbase-binding</artifactId>
+ <name>Couchbase Java SDK Binding</name>
+ <packaging>jar</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.couchbase.client</groupId>
+ <artifactId>java-client</artifactId>
+ <version>${couchbase2.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.couchbase.client</groupId>
+ <artifactId>couchbase-client</artifactId>
+ <version>${couchbase1.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.5.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.yahoo.ycsb</groupId>
+ <artifactId>core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>${maven.assembly.version}</version>
+ <configuration>
+ <descriptorRefs>
+ <descriptorRef>jar-with-dependencies</descriptorRef>
+ </descriptorRefs>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
View
337 couchbase/src/main/java/com/yahoo/ycsb/db/Couchbase1Client.java
@@ -0,0 +1,337 @@
+/**
+ * Copyright (C) 2015 Couchbase, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALING
+ * IN THE SOFTWARE.
+ */
+package com.yahoo.ycsb.db;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.yahoo.ycsb.ByteIterator;
+import com.yahoo.ycsb.DB;
+import com.yahoo.ycsb.DBException;
+import com.yahoo.ycsb.StringByteIterator;
+import net.spy.memcached.PersistTo;
+import net.spy.memcached.ReplicateTo;
+import net.spy.memcached.internal.OperationFuture;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.util.*;
+
+public class Couchbase1Client extends DB {
+
+ public static final String HOST_PROPERTY = "couchbase.host";
+ public static final String BUCKET_PROPERTY = "couchbase.bucket";
+ public static final String PASSWORD_PROPERTY = "couchbase.password";
+ public static final String CHECKF_PROPERTY = "couchbase.checkFutures";
+ public static final String PERSIST_PROPERTY = "couchbase.persistTo";
+ public static final String REPLICATE_PROPERTY = "couchbase.replicateTo";
+ public static final String JSON_PROPERTY = "couchbase.json";
+
+ public static final int OK = 0;
+ public static final int FAILURE = 1;
+
+ protected static final ObjectMapper JSON_MAPPER = new ObjectMapper();
+
+ private com.couchbase.client.CouchbaseClient client;
+ private PersistTo persistTo;
+ private ReplicateTo replicateTo;
+ private boolean checkFutures;
+ private boolean useJson;
+ private final Logger log = LoggerFactory.getLogger(getClass());
+
+ @Override
+ public void init() throws DBException {
+ Properties props = getProperties();
+
+ String host = props.getProperty(HOST_PROPERTY, "127.0.0.1");
+ String bucket = props.getProperty(BUCKET_PROPERTY, "default");
+ String password = props.getProperty(PASSWORD_PROPERTY, "");
+
+ checkFutures = props.getProperty(CHECKF_PROPERTY, "true").equals("true");
+ useJson = props.getProperty(JSON_PROPERTY, "true").equals("true");
+
+ persistTo = parsePersistTo(props.getProperty(PERSIST_PROPERTY, "0"));
+ replicateTo = parseReplicateTo(props.getProperty(REPLICATE_PROPERTY, "0"));
+
+ Properties systemProperties = System.getProperties();
+ systemProperties.put("net.spy.log.LoggerImpl", "net.spy.memcached.compat.log.SLF4JLogger");
+ System.setProperties(systemProperties);
+
+ try {
+ client = new com.couchbase.client.CouchbaseClient(
+ Arrays.asList(new URI("http://" + host + ":8091/pools")),
+ bucket,
+ password
+ );
+ } catch (Exception e) {
+ throw new DBException("Could not create CouchbaseClient object.", e);
+ }
+ }
+
+ /**
+ * Parse the replicate property into the correct enum.
+ *
+ * @param property the stringified property value.
+ * @return the correct enum.
+ * @throws DBException if parsing the property did fail.
+ */
+ private ReplicateTo parseReplicateTo(final String property) throws DBException {
+ int value = Integer.parseInt(property);
+
+ switch (value) {
+ case 0:
+ return ReplicateTo.ZERO;
+ case 1:
+ return ReplicateTo.ONE;
+ case 2:
+ return ReplicateTo.TWO;
+ case 3:
+ return ReplicateTo.THREE;
+ default:
+ throw new DBException(REPLICATE_PROPERTY + " must be between 0 and 3");
+ }
+ }
+
+ /**
+ * Parse the persist property into the correct enum.
+ *
+ * @param property the stringified property value.
+ * @return the correct enum.
+ * @throws DBException if parsing the property did fail.
+ */
+ private PersistTo parsePersistTo(final String property) throws DBException {
+ if (property.toLowerCase().equals("master")) {
+ return PersistTo.MASTER;
+ }
+
+ int value = Integer.parseInt(property);
+
+ switch (value) {
+ case 0:
+ return PersistTo.ZERO;
+ case 1:
+ return PersistTo.ONE;
+ case 2:
+ return PersistTo.TWO;
+ case 3:
+ return PersistTo.THREE;
+ case 4:
+ return PersistTo.FOUR;
+ default:
+ throw new DBException(PERSIST_PROPERTY + " must be between 0 and 4 or master");
+ }
+ }
+
+ /**
+ * Shutdown the client.
+ */
+ @Override
+ public void cleanup() {
+ client.shutdown();
+ }
+
+ @Override
+ public int read(final String table, final String key, final Set<String> fields,
+ final HashMap<String, ByteIterator> result) {
+ String formattedKey = formatKey(table, key);
+
+ try {
+ Object loaded = client.get(formattedKey);
+
+ if (loaded == null) {
+ return FAILURE;
+ }
+
+ decode(loaded, fields, result);
+ return OK;
+ } catch (Exception e) {
+ if (log.isErrorEnabled()) {
+ log.error("Could not read value for key " + formattedKey, e);
+ }
+ return FAILURE;
+ }
+ }
+
+ /**
+ * Scan is currently not implemented.
+ *
+ * @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 FAILURE, because not implemented yet.
+ */
+ @Override
+ public int scan(final String table, final String startkey, final int recordcount,
+ final Set<String> fields, final Vector<HashMap<String, ByteIterator>> result) {
+ return FAILURE;
+ }
+
+ @Override
+ public int update(final String table, final String key, final HashMap<String, ByteIterator> values) {
+ String formattedKey = formatKey(table, key);
+
+ try {
+ final OperationFuture<Boolean> future = client.replace(
+ formattedKey,
+ encode(values),
+ persistTo,
+ replicateTo
+ );
+ return checkFutureStatus(future);
+ } catch (Exception e) {
+ if (log.isErrorEnabled()) {
+ log.error("Could not update value for key " + formattedKey, e);
+ }
+ return FAILURE;
+ }
+ }
+
+ @Override
+ public int insert(final String table, final String key, final HashMap<String, ByteIterator> values) {
+ String formattedKey = formatKey(table, key);
+
+ try {
+ final OperationFuture<Boolean> future = client.add(
+ formattedKey,
+ encode(values),
+ persistTo,
+ replicateTo
+ );
+ return checkFutureStatus(future);
+ } catch (Exception e) {
+ if (log.isErrorEnabled()) {
+ log.error("Could not insert value for key " + formattedKey, e);
+ }
+ return FAILURE;
+ }
+ }
+
+ @Override
+ public int delete(final String table, final String key) {
+ String formattedKey = formatKey(table, key);
+
+ try {
+ final OperationFuture<Boolean> future = client.delete(formattedKey, persistTo, replicateTo);
+ return checkFutureStatus(future);
+ } catch (Exception e) {
+ if (log.isErrorEnabled()) {
+ log.error("Could not delete value for key " + formattedKey, e);
+ }
+ return FAILURE;
+ }
+ }
+
+ /**
+ * Prefix the key with the given prefix, to establish a unique namespace.
+ *
+ * @param prefix the prefix to use.
+ * @param key the actual key.
+ * @return the formatted and prefixed key.
+ */
+ private String formatKey(final String prefix, final String key) {
+ return prefix + ":" + key;
+ }
+
+ /**
+ * Wrapper method that either inspects the future or not.
+ *
+ * @param future the future to potentially verify.
+ * @return the status of the future result.
+ */
+ private int checkFutureStatus(final OperationFuture<?> future) {
+ if (checkFutures) {
+ return future.getStatus().isSuccess() ? OK : FAILURE;
+ } else {
+ return OK;
+ }
+ }
+
+ /**
+ * Decode the object from server into the storable result.
+ *
+ * @param source the loaded object.
+ * @param fields the fields to check.
+ * @param dest the result passed back to the ycsb core.
+ */
+ private void decode(final Object source, final Set<String> fields,
+ final HashMap<String, ByteIterator> dest) {
+ if (useJson) {
+ try {
+ JsonNode json = JSON_MAPPER.readTree((String) source);
+ boolean checkFields = fields != null && fields.size() > 0;
+ for (Iterator<Map.Entry<String, JsonNode>> jsonFields = json.fields(); jsonFields.hasNext(); ) {
+ Map.Entry<String, JsonNode> jsonField = jsonFields.next();
+ String name = jsonField.getKey();
+ if (checkFields && fields.contains(name)) {
+ continue;
+ }
+ JsonNode jsonValue = jsonField.getValue();
+ if (jsonValue != null && !jsonValue.isNull()) {
+ dest.put(name, new StringByteIterator(jsonValue.asText()));
+ }
+ }
+ } catch (Exception e) {
+ throw new RuntimeException("Could not decode JSON");
+ }
+ } else {
+ HashMap<String, String> converted = (HashMap<String, String>) source;
+ for (Map.Entry<String, String> entry : converted.entrySet()) {
+ dest.put(entry.getKey(), new StringByteIterator(entry.getValue()));
+ }
+ }
+ }
+
+ /**
+ * Encode the object for couchbase storage.
+ *
+ * @param source the source value.
+ * @return the storable object.
+ */
+ private Object encode(final HashMap<String, ByteIterator> source) {
+ HashMap<String, String> stringMap = StringByteIterator.getStringMap(source);
+ if (!useJson) {
+ return stringMap;
+ }
+
+ ObjectNode node = JSON_MAPPER.createObjectNode();
+ for (Map.Entry<String, String> pair : stringMap.entrySet()) {
+ node.put(pair.getKey(), pair.getValue());
+ }
+ JsonFactory jsonFactory = new JsonFactory();
+ Writer writer = new StringWriter();
+ try {
+ JsonGenerator jsonGenerator = jsonFactory.createGenerator(writer);
+ JSON_MAPPER.writeTree(jsonGenerator, node);
+ } catch (Exception e) {
+ throw new RuntimeException("Could not encode JSON value");
+ }
+ return writer.toString();
+ }
+
+}
View
191 couchbase/src/main/java/com/yahoo/ycsb/db/Couchbase2Client.java
@@ -0,0 +1,191 @@
+/**
+ * Copyright (C) 2015 Couchbase, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALING
+ * IN THE SOFTWARE.
+ */
+package com.yahoo.ycsb.db;
+
+import com.couchbase.client.java.Bucket;
+import com.couchbase.client.java.Cluster;
+import com.couchbase.client.java.CouchbaseCluster;
+import com.couchbase.client.java.PersistTo;
+import com.couchbase.client.java.ReplicateTo;
+import com.couchbase.client.java.document.JsonDocument;
+import com.couchbase.client.java.document.json.JsonObject;
+import com.yahoo.ycsb.ByteIterator;
+import com.yahoo.ycsb.DB;
+import com.yahoo.ycsb.DBException;
+import com.yahoo.ycsb.StringByteIterator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.HashMap;
+import java.util.Set;
+import java.util.Vector;
+
+public class Couchbase2Client extends DB {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Couchbase2Client.class);
+
+ private static final int SUCCESS = 0;
+ private static final int ERROR = 1;
+
+ private static Bucket bucket;
+ private static Cluster cluster;
+
+ private static PersistTo persistTo;
+ private static ReplicateTo replicateTo;
+
+ @Override
+ public void init() throws DBException {
+ String host = getProperties().getProperty("couchbase.host", "127.0.0.1");
+ String bucketName = getProperties().getProperty("couchbase.bucket", "default");
+ String bucketPassword = getProperties().getProperty("couchbase.password", "");
+
+ cluster = CouchbaseCluster.create(host);
+ bucket = cluster.openBucket(bucketName, bucketPassword);
+
+ persistTo = parsePersistTo(getProperties().getProperty("couchbase.persistTo", "0"));
+ replicateTo = parseReplicateTo(getProperties().getProperty("couchbase.replicateTo", "0"));
+ }
+
+ private static PersistTo parsePersistTo(final String persistTo) {
+ if (persistTo.toLowerCase().equals("master")) {
+ return PersistTo.MASTER;
+ } else if (persistTo.equals("1")) {
+ return PersistTo.ONE;
+ } else if (persistTo.equals("2")) {
+ return PersistTo.TWO;
+ } else if (persistTo.equals("3")) {
+ return PersistTo.THREE;
+ } else if (persistTo.equals("4")) {
+ return PersistTo.FOUR;
+ } else {
+ return PersistTo.NONE;
+ }
+ }
+
+ private static ReplicateTo parseReplicateTo(final String replicateTo) {
+ if (replicateTo.equals("1")) {
+ return ReplicateTo.ONE;
+ } else if (replicateTo.equals("2")) {
+ return ReplicateTo.TWO;
+ } else if (replicateTo.equals("3")) {
+ return ReplicateTo.THREE;
+ } else {
+ return ReplicateTo.NONE;
+ }
+ }
+
+ @Override
+ public void cleanup() throws DBException {
+ cluster.disconnect();
+ }
+
+ @Override
+ public int read(String table, String key, Set<String> fields, HashMap<String, ByteIterator> result) {
+ String formattedKey = formatKey(table, key);
+
+ try {
+ JsonDocument loaded = bucket.get(formattedKey);
+ if (loaded == null) {
+ return ERROR;
+ }
+
+ if (fields == null) {
+ for (String field : loaded.content().getNames()) {
+ result.put(field, new StringByteIterator(loaded.content().getString(field)));
+ }
+ } else {
+ for (String field : fields) {
+ result.put(field, new StringByteIterator(loaded.content().getString(field)));
+ }
+ }
+
+ return SUCCESS;
+ } catch (Exception ex) {
+ if (LOGGER.isErrorEnabled()) {
+ LOGGER.error("Could not insert key " + formattedKey, ex);
+ }
+ return ERROR;
+ }
+ }
+
+ @Override
+ public int scan(String table, String startkey, int recordcount, Set<String> fields,
+ Vector<HashMap<String, ByteIterator>> result) {
+ return ERROR;
+ }
+
+ @Override
+ public int update(String table, String key, HashMap<String, ByteIterator> values) {
+ String formattedKey = formatKey(table, key);
+
+ try {
+ JsonObject payload = JsonObject.empty();
+ for (String k : values.keySet()) {
+ payload.put(k, values.get(k).toString());
+ }
+ bucket.replace(JsonDocument.create(formattedKey, payload), persistTo, replicateTo);
+ return SUCCESS;
+ } catch (Exception ex) {
+ if (LOGGER.isErrorEnabled()) {
+ LOGGER.error("Could not update key " + formattedKey, ex);
+ }
+ return ERROR;
+ }
+ }
+
+ @Override
+ public int insert(String table, String key, HashMap<String, ByteIterator> values) {
+ String formattedKey = formatKey(table, key);
+
+ try {
+ JsonObject payload = JsonObject.empty();
+ for (String k : values.keySet()) {
+ payload.put(k, values.get(k).toString());
+ }
+ bucket.insert(JsonDocument.create(formattedKey, payload), persistTo, replicateTo);
+ return SUCCESS;
+ } catch (Exception ex) {
+ if (LOGGER.isErrorEnabled()) {
+ LOGGER.error("Could not insert key " + formattedKey, ex);
+ }
+ return ERROR;
+ }
+ }
+
+ @Override
+ public int delete(String table, String key) {
+ String formattedKey = formatKey(table, key);
+ try {
+ bucket.remove(formattedKey, persistTo, replicateTo);
+ return SUCCESS;
+ } catch (Exception ex) {
+ if (LOGGER.isErrorEnabled()) {
+ LOGGER.error("Could not delete key " + formattedKey, ex);
+ }
+ return ERROR;
+ }
+ }
+
+ private static String formatKey(final String table, final String key) {
+ return table + "-" + key;
+ }
+
+}
View
3 pom.xml
@@ -57,6 +57,8 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<thrift.version>0.8.0</thrift.version>
<hypertable.version>0.9.5.6</hypertable.version>
+ <couchbase2.version>2.1.2</couchbase2.version>
+ <couchbase1.version>1.4.9</couchbase1.version>
</properties>
<modules>
@@ -78,6 +80,7 @@
<module>redis</module>
<module>voldemort</module>
<module>distribution</module>
+ <module>couchbase</module>
</modules>
<build>

No commit comments for this range

Something went wrong with that request. Please try again.