diff --git a/bin/ycsb b/bin/ycsb index 3e954c88b4..b36b54eb6c 100755 --- a/bin/ycsb +++ b/bin/ycsb @@ -76,6 +76,7 @@ DATABASES = { "geode" : "com.yahoo.ycsb.db.GeodeClient", "googlebigtable" : "com.yahoo.ycsb.db.GoogleBigtableClient", "googledatastore" : "com.yahoo.ycsb.db.GoogleDatastoreClient", + "griddb" : "com.yahoo.ycsb.db.griddb.GridDBClient", "hbase098" : "com.yahoo.ycsb.db.HBaseClient", "hbase10" : "com.yahoo.ycsb.db.HBaseClient10", "hbase12" : "com.yahoo.ycsb.db.hbase12.HBaseClient12", diff --git a/distribution/pom.xml b/distribution/pom.xml index ad825869b5..bb0827803f 100644 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -134,6 +134,11 @@ LICENSE file. googlebigtable-binding ${project.version} + + com.yahoo.ycsb + griddb-binding + ${project.version} + com.yahoo.ycsb hbase098-binding diff --git a/griddb/README.md b/griddb/README.md new file mode 100644 index 0000000000..4f96a65256 --- /dev/null +++ b/griddb/README.md @@ -0,0 +1,81 @@ + + +## Overview + +GridDB (https://github.com/griddb/griddb_nosql) is a highly scalable NoSQL database best suited for IoT and Big Data. + +This is GridDB Binding for YCSB. + +## Environment +Library building and program execution have been checked in the following environment. + + OS: CentOS 6.9(x64). + Java: JDK 1.8.0_191 + Maven: 3.5.4 + Python: 2.6.6 + +## Quick start + +### Preparations + +Clone the YCSB source code from git repository: + + git clone https://github.com/brianfrankcooper/YCSB.git + cd YCSB + +### Build + +Run following command + + $ mvn -pl com.yahoo.ycsb:griddb-binding -am clean package + +Then, some jar files are created in: + + griddb/target + +### GridDB setup + +Please set the number of cpu core as /dataStore/concurrency in gs_node.json and "32KB" as /dataStore/storeBlockSize in gs_cluster.json. + +### Run YCSB + +GridDB needs to be started in advance. +Please execute our program with fieldcount=10 and fieldlength=100. +First, load the data: + + ./bin/ycsb load griddb -P workloads/workloada + -p notificationAddress= + -p notificationPort= + -p clusterName= + -p userName= + -p password= + -p fieldcount=10 + -p fieldlength=100 + +Then, run the workload: + + ./bin/ycsb run griddb -P workloads/workloada + -p notificationAddress= + -p notificationPort= + -p clusterName= + -p userName= + -p password= + -p fieldcount=10 + -p fieldlength=100 + diff --git a/griddb/pom.xml b/griddb/pom.xml new file mode 100644 index 0000000000..7a8d476b8a --- /dev/null +++ b/griddb/pom.xml @@ -0,0 +1,52 @@ + + + + + 4.0.0 + + com.yahoo.ycsb + binding-parent + 0.16.0-SNAPSHOT + ../binding-parent + + + griddb-binding + GridDB Binding + jar + + + + com.yahoo.ycsb + core + ${project.version} + provided + + + com.github.griddb + gridstore + ${griddb.version} + + + junit + junit + 4.12 + test + + + diff --git a/griddb/src/main/java/com/yahoo/ycsb/db/griddb/GridDBClient.java b/griddb/src/main/java/com/yahoo/ycsb/db/griddb/GridDBClient.java new file mode 100644 index 0000000000..511b2a69ec --- /dev/null +++ b/griddb/src/main/java/com/yahoo/ycsb/db/griddb/GridDBClient.java @@ -0,0 +1,333 @@ +/** + * Copyright (c) 2018 TOSHIBA Digital Solutions Corporation. + * Copyright (c) 2018 YCSB contributors. + * + * 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.griddb; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Map; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import java.util.Vector; +import java.util.logging.Logger; + +import com.toshiba.mwcloud.gs.ColumnInfo; +import com.toshiba.mwcloud.gs.Container; +import com.toshiba.mwcloud.gs.ContainerInfo; +import com.toshiba.mwcloud.gs.ContainerType; +import com.toshiba.mwcloud.gs.GSException; +import com.toshiba.mwcloud.gs.GSType; +import com.toshiba.mwcloud.gs.GridStore; +import com.toshiba.mwcloud.gs.GridStoreFactory; +import com.toshiba.mwcloud.gs.PartitionController; +import com.toshiba.mwcloud.gs.Row; +import com.yahoo.ycsb.ByteArrayByteIterator; +import com.yahoo.ycsb.ByteIterator; +import com.yahoo.ycsb.DBException; +import com.yahoo.ycsb.Status; + +/** + * A class representing GridDBClient. + * + */ +public class GridDBClient extends com.yahoo.ycsb.DB { + //(A)multicast method + private String notificationAddress = ""; // "239.0.0.1" + private String notificationPort = ""; // "31999" + //(B)fixed list method + private String notificationMember = ""; // "10.0.0.12:10001,10.0.0.13:10001,10.0.0.14:10001" + + private String userName = ""; // + private String password = ""; // + private String clusterName = ""; // "ycsbCluster" + + + public static final String VALUE_COLUMN_NAME_PREFIX= "field"; + public static final int ROW_KEY_COLUMN_POS = 0; + + private String containerPrefix = ""; + + public static final int DEFAULT_CACHE_CONTAINER_NUM = 1000; + public static final int FIELD_NUM = 10; + + private int numContainer = 0; // Sets PartitionNum + public static final GSType SCHEMA_TYPE = GSType.STRING; + + private GridStore store; + private ContainerInfo containerInfo = null; + private static final Logger LOGGER = Logger.getLogger(GridDBClient.class.getName()); + + class RowComparator implements Comparator { + public int compare(Row row1, Row row2) throws NullPointerException { + int result = 0; + try { + Object val1 = row1.getValue(0); + Object val2 = row2.getValue(0); + result = ((String)val1).compareTo((String)val2); + } catch (GSException e) { + LOGGER.severe("There is a exception: " + e.getMessage()); + throw new NullPointerException(); + } + return result; + } + } + + public void init() throws DBException { + LOGGER.info("GridDBClient"); + + final Properties props = getProperties(); + notificationAddress = props.getProperty("notificationAddress"); + notificationPort = props.getProperty("notificationPort"); + notificationMember = props.getProperty("notificationMember"); + clusterName = props.getProperty("clusterName"); + userName = props.getProperty("userName"); + password = props.getProperty("password"); + containerPrefix = props.getProperty("table", "usertable") + "@"; + String fieldcount = props.getProperty("fieldcount"); + String fieldlength = props.getProperty("fieldlength"); + + LOGGER.info("notificationAddress=" + notificationAddress + " notificationPort=" + notificationPort + + " notificationMember=" + notificationMember); + LOGGER.info("clusterName=" + clusterName + " userName=" + userName); + LOGGER.info("fieldcount=" + fieldcount + " fieldlength=" + fieldlength); + + + final Properties gridstoreProp = new Properties(); + if (clusterName == null || userName == null || password == null) { + LOGGER.severe("[ERROR] clusterName or userName or password argument not specified"); + throw new DBException(); + } + if (fieldcount == null || fieldlength == null) { + LOGGER.severe("[ERROR] fieldcount or fieldlength argument not specified"); + throw new DBException(); + } else { + if (!fieldcount.equals(String.valueOf(FIELD_NUM)) || !fieldlength.equals("100")) { + LOGGER.severe("[ERROR] Invalid argment: fieldcount or fieldlength"); + throw new DBException(); + } + } + if (notificationAddress != null) { + if (notificationPort == null) { + LOGGER.severe("[ERROR] notificationPort argument not specified"); + throw new DBException(); + } + //(A)multicast method + gridstoreProp.setProperty("notificationAddress", notificationAddress); + gridstoreProp.setProperty("notificationPort", notificationPort); + } else if (notificationMember != null) { + //(B)fixed list method + gridstoreProp.setProperty("notificationMember", notificationMember); + } else { + LOGGER.severe("[ERROR] notificationAddress and notificationMember argument not specified"); + throw new DBException(); + } + gridstoreProp.setProperty("clusterName", clusterName); + gridstoreProp.setProperty("user", userName); + gridstoreProp.setProperty("password", password); + + gridstoreProp.setProperty("containerCacheSize", String.valueOf(DEFAULT_CACHE_CONTAINER_NUM)); + + List columnInfoList = new ArrayList(); + ColumnInfo keyInfo = new ColumnInfo("key", SCHEMA_TYPE); + columnInfoList.add(keyInfo); + for (int i = 0; i < FIELD_NUM; i++) { + String columnName = String.format(VALUE_COLUMN_NAME_PREFIX + "%d", i); + ColumnInfo info = new ColumnInfo(columnName, SCHEMA_TYPE); + columnInfoList.add(info); + } + containerInfo = new ContainerInfo(null, ContainerType.COLLECTION, columnInfoList, true); + + try { + GridStoreFactory.getInstance().setProperties(gridstoreProp); + store = GridStoreFactory.getInstance().getGridStore(gridstoreProp); + PartitionController controller = store.getPartitionController(); + numContainer = controller.getPartitionCount(); + + for(int k = 0; k < numContainer; k++) { + String name = containerPrefix + k; + store.putContainer(name, containerInfo, false); + } + } catch (GSException e) { + LOGGER.severe("Exception: " + e.getMessage()); + throw new DBException(); + } + + LOGGER.info("numContainer=" + numContainer + " containerCasheSize=" + + String.valueOf(DEFAULT_CACHE_CONTAINER_NUM)); + + } + + public void cleanup() throws DBException { + try { + store.close(); + } catch (GSException e) { + LOGGER.severe("Exception when close." + e.getMessage()); + throw new DBException(); + } + } + + public Status read(String table, String key, Set fields, Map result) { + try { + + Object rowKey = makeRowKey(key); + String containerKey = makeContainerKey(key); + + final Container container = store.getContainer(containerKey); + if(container == null) { + LOGGER.severe("[ERROR]getCollection " + containerKey + " in read()"); + return Status.ERROR; + } + + Row targetRow = container.get(rowKey); + if (targetRow == null) { + LOGGER.severe("[ERROR]get(rowKey) in read()"); + return Status.ERROR; + } + + for (int i = 1; i < containerInfo.getColumnCount(); i++) { + result.put(containerInfo.getColumnInfo(i).getName(), + new ByteArrayByteIterator(targetRow.getValue(i).toString().getBytes())); + } + + return Status.OK; + + } catch (GSException e) { + LOGGER.severe("Exception: " + e.getMessage()); + return Status.ERROR; + } + } + + public Status scan(String table, String startkey, int recordcount, Set fields, + Vector> result) { + LOGGER.severe("[ERROR]scan() not supported"); + return Status.ERROR; + } + + public Status update(String table, String key, Map values) { + try { + Object rowKey = makeRowKey(key); + String containerKey = makeContainerKey(key); + + final Container container = store.getContainer(containerKey); + if(container == null) { + LOGGER.severe("[ERROR]getCollection " + containerKey + " in update()"); + return Status.ERROR; + } + + Row targetRow = container.get(rowKey); + if (targetRow == null) { + LOGGER.severe("[ERROR]get(rowKey) in update()"); + return Status.ERROR; + } + + int setCount = 0; + for (int i = 1; i < containerInfo.getColumnCount() && setCount < values.size(); i++) { + containerInfo.getColumnInfo(i).getName(); + ByteIterator byteIterator = values.get(containerInfo.getColumnInfo(i).getName()); + if (byteIterator != null) { + Object value = makeValue(byteIterator); + targetRow.setValue(i, value); + setCount++; + } + } + if (setCount != values.size()) { + LOGGER.severe("Error setCount = " + setCount); + return Status.ERROR; + } + + container.put(targetRow); + + return Status.OK; + } catch (GSException e) { + LOGGER.severe("Exception: " + e.getMessage()); + return Status.ERROR; + } + } + + public Status insert(String table, String key, Map values) { + try { + + Object rowKey = makeRowKey(key); + String containerKey = makeContainerKey(key); + + final Container container = store.getContainer(containerKey); + if(container == null) { + LOGGER.severe("[ERROR]getCollection " + containerKey + " in insert()"); + } + + Row row = container.createRow(); + + row.setValue(ROW_KEY_COLUMN_POS, rowKey); + + for (int i = 1; i < containerInfo.getColumnCount(); i++) { + ByteIterator byteIterator = values.get(containerInfo.getColumnInfo(i).getName()); + Object value = makeValue(byteIterator); + row.setValue(i, value); + } + + container.put(row); + + } catch (GSException e) { + LOGGER.severe("Exception: " + e.getMessage()); + return Status.ERROR; + } + + return Status.OK; + } + + public Status delete(String table, String key) { + try { + Object rowKey = makeRowKey(key); + String containerKey = makeContainerKey(key); + + final Container container = store.getContainer(containerKey); + if(container == null) { + LOGGER.severe("[ERROR]getCollection " + containerKey + " in read()"); + return Status.ERROR; + } + + boolean isDelete = container.remove(rowKey); + if (!isDelete) { + LOGGER.severe("[ERROR]remove(rowKey) in remove()"); + return Status.ERROR; + } + }catch (GSException e) { + LOGGER.severe("Exception: " + e.getMessage()); + return Status.ERROR; + } + return Status.OK; + } + + protected String makeContainerKey(String key) { + return containerPrefix + Math.abs(key.hashCode() % numContainer); + } + + protected Object makeRowKey(String key) { + return key; + } + + protected Object makeValue(ByteIterator byteIterator) { + return byteIterator.toString(); + } + + protected Object makeQueryLiteral(Object value) { + return "'" + value.toString() + "'"; + } +} diff --git a/griddb/src/main/java/com/yahoo/ycsb/db/griddb/package-info.java b/griddb/src/main/java/com/yahoo/ycsb/db/griddb/package-info.java new file mode 100644 index 0000000000..c5b4a9b2df --- /dev/null +++ b/griddb/src/main/java/com/yahoo/ycsb/db/griddb/package-info.java @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2018 TOSHIBA Digital Solutions Corporation. + * Copyright (c) 2018 YCSB contributors. + * + * 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 GridDB. + */ +package com.yahoo.ycsb.db.griddb; diff --git a/griddb/src/test/java/com/yahoo/ycsb/db/griddb/GridDBClientTest.java b/griddb/src/test/java/com/yahoo/ycsb/db/griddb/GridDBClientTest.java new file mode 100644 index 0000000000..562dce4113 --- /dev/null +++ b/griddb/src/test/java/com/yahoo/ycsb/db/griddb/GridDBClientTest.java @@ -0,0 +1,330 @@ +/** + * Copyright (c) 2018 TOSHIBA Digital Solutions Corporation. + * Copyright (c) 2018 YCSB contributors. + * + * 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.griddb; + +import static org.hamcrest.CoreMatchers.not; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.Assert.*; +import static org.junit.Assume.assumeNoException; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Properties; +import java.util.Set; + +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.toshiba.mwcloud.gs.ColumnInfo; +import com.toshiba.mwcloud.gs.ContainerInfo; +import com.toshiba.mwcloud.gs.ContainerType; +import com.toshiba.mwcloud.gs.GSException; +import com.toshiba.mwcloud.gs.GSType; +import com.toshiba.mwcloud.gs.GridStore; +import com.toshiba.mwcloud.gs.GridStoreFactory; +import com.yahoo.ycsb.ByteIterator; +import com.yahoo.ycsb.DB; +import com.yahoo.ycsb.DBException; +import com.yahoo.ycsb.Status; +import com.yahoo.ycsb.StringByteIterator; +import com.yahoo.ycsb.measurements.Measurements; +import com.yahoo.ycsb.workloads.CoreWorkload; + +public class GridDBClientTest { + // Default GridbDB port + private static final int GRIDDB_DEFAULT_PORT = 10040; + + //GridDBDatastore configuration + private final static String TEST_TABLE = "testtable"; + private final static String NOTIFICATION_PORT = "31999";//default is 31999 + private final static String NOTIFICATION_ADDR = "239.0.0.1";//default is 239.0.0.1 + private final static String CLUSTER_NAME = "ycsbcluster";//Fill your cluster name + private final static String USER_NAME = "admin";//Fill your user name + private final static String PASS = "admin";//Fill your password + private final static int FIELD_COUNT = 10; + private final static String FIELD_LENGTH = "100"; + + private DB myClient = null; + private final static String DEFAULT_ROW_KEY = "user1"; + public static final String VALUE_COLUMN_NAME_PREFIX= "field"; + private ContainerInfo containerInfo = null; + private GridStore store; + + /** + * Verifies the GridDB process (or some process) is running on port 10040, if + * not the tests are skipped. + */ + @BeforeClass + public static void setUpBeforeClass() { + // Test if we can connect. + Socket socket = null; + try { + // Connect + socket = new Socket(InetAddress.getLocalHost(), GRIDDB_DEFAULT_PORT); + assertThat("Socket is not bound.", socket.getLocalPort(), not(-1)); + } catch (IOException connectFailed) { + assumeNoException("GridDB is not running. Skipping tests.", + connectFailed); + } finally { + if (socket != null) { + try { + socket.close(); + } catch (IOException ignore) { + // Ignore. + } + } + socket = null; + } + } + + /** + * Create properties for configuration to get client + * Create data table to test + */ + @Before + public void setUp() throws Exception { + + Properties p = new Properties(); + p.setProperty("notificationAddress", NOTIFICATION_ADDR); + p.setProperty("notificationPort", NOTIFICATION_PORT); + p.setProperty("clusterName", CLUSTER_NAME); + p.setProperty("userName", USER_NAME); + p.setProperty("user", USER_NAME); + p.setProperty("password", PASS); + p.setProperty("fieldcount", String.valueOf(FIELD_COUNT)); + p.setProperty("fieldlength", FIELD_LENGTH); + + Measurements.setProperties(p); + final CoreWorkload workload = new CoreWorkload(); + workload.init(p); + getDB(p); + + // Create data table to test + // List of columns + List columnInfoList = new ArrayList(); + ColumnInfo keyInfo = new ColumnInfo("key", GSType.STRING); + columnInfoList.add(keyInfo); + for (int i = 0; i < FIELD_COUNT; i++) { + String columnName = String.format(VALUE_COLUMN_NAME_PREFIX + "%d", i); + ColumnInfo info = new ColumnInfo(columnName, GSType.STRING); + columnInfoList.add(info); + } + containerInfo = new ContainerInfo(null, ContainerType.COLLECTION, columnInfoList, true); + + try { + GridStoreFactory.getInstance().setProperties(p); + store = GridStoreFactory.getInstance().getGridStore(p); + store.putContainer(TEST_TABLE, containerInfo, false); + } catch (GSException e) { + e.printStackTrace(); + throw new DBException(); + } + } + + /** + * Insert data to GridbDB database for testing + */ + private void insertToDatabase() { + HashMap values = new HashMap(); + + // The number of field in container info is 10 + for (int i = 0; i < FIELD_COUNT; i++) { + values.put(VALUE_COLUMN_NAME_PREFIX + i, new StringByteIterator("value" + i)); + } + myClient.insert(TEST_TABLE, DEFAULT_ROW_KEY, values); + } + + @Test + public void testReadNoExistedRow() { + Set fields = Collections.singleton("field0"); + + HashMap result = new HashMap(); + insertToDatabase(); + Status readStatus = myClient.read(TEST_TABLE, "Missing row", fields, result); + + assertEquals(readStatus, Status.ERROR); + assertEquals(result.size(), 0); + } + + @Test + public void testReadSingleRow() { + Set fields = Collections.singleton("field1"); + HashMap result = new HashMap(); + insertToDatabase(); + Status readStatus = myClient.read(TEST_TABLE, DEFAULT_ROW_KEY, fields, result); + + assertEquals(readStatus, Status.OK); + assertNotEquals(result.entrySet(), 0); + + for (String key : fields) { + ByteIterator iter = result.get(key); + byte[] byteArray1 = iter.toArray(); + + String value = new String(byteArray1); + assertEquals(value, "value1"); + } + } + + @Test + public void testReadAll() { + HashMap result = new HashMap(); + insertToDatabase(); + Status readStatus = myClient.read(TEST_TABLE, DEFAULT_ROW_KEY, null, result); + + assertEquals(readStatus, Status.OK); + assertEquals(result.size(), FIELD_COUNT); + + for (int i = 0; i < FIELD_COUNT; i++) { + ByteIterator iter = result.get("field" + i); + byte[] byteArray1 = iter.toArray(); + + String value = new String(byteArray1); + assertEquals(value, "value" + i); + } + } + + @Test + public void testUpdate() { + HashMap result = new HashMap(); + HashMap values = new HashMap(); + insertToDatabase(); + + String keyForUpdate = "field2"; + Set fields = Collections.singleton(keyForUpdate); + + String strValueToUpdate = "new_value_2"; + ByteIterator valForUpdate = new StringByteIterator(strValueToUpdate); + values.put(keyForUpdate, valForUpdate); + + Status updateStatus = myClient.update(TEST_TABLE, DEFAULT_ROW_KEY, values); + assertEquals(updateStatus, Status.OK); + + // After update, we read the update row for get new value + myClient.read(TEST_TABLE, DEFAULT_ROW_KEY, fields, result); + assertNotEquals(result.entrySet(), 0); + + boolean found = false; + for (int i = 0; i < FIELD_COUNT; i++) { + ByteIterator iter = result.get("field" + i); + byte[] byteArray1 = iter.toArray(); + + String value = new String(byteArray1); + // check result has row value is new update value or not + if (value.equals(strValueToUpdate)) { + found = true; + } + } + assertEquals(found, true); + } + + @Test + public void testInsert() { + HashMap values = new HashMap(); + HashMap result = new HashMap(); + + // The number of field in container info is 10 + for (int i = 0; i < FIELD_COUNT; i++) { + values.put("field" + i, new StringByteIterator("value" + i)); + } + + Status insertStatus = myClient.insert(TEST_TABLE, DEFAULT_ROW_KEY, values); + + assertEquals(insertStatus, Status.OK); + + myClient.read(TEST_TABLE, DEFAULT_ROW_KEY, null, result); + + assertEquals(result.size(), FIELD_COUNT); + + for (int i = 0; i < FIELD_COUNT; i++) { + ByteIterator iter = result.get("field" + i); + byte[] byteArray1 = iter.toArray(); + + String value = new String(byteArray1); + assertEquals(value, "value" + i); + } + } + + @Test + public void testDelete() { + HashMap result = new HashMap(); + insertToDatabase(); + + Status deleteStatus = myClient.delete(TEST_TABLE, DEFAULT_ROW_KEY); + assertEquals(deleteStatus, Status.OK); + + Status readStatus = myClient.read(TEST_TABLE, DEFAULT_ROW_KEY, null, result); + assertEquals(readStatus, Status.ERROR); + assertEquals(result.size(), 0); + } + + @Test + public void testCombination() { + final int LOOP_COUNT = 3; + for (int i = 0; i < LOOP_COUNT; i++) { + testReadNoExistedRow(); + testReadSingleRow(); + testReadAll(); + testInsert(); + testUpdate(); + testDelete(); + } + } + + /** + * Stops the test client. + */ + @After + public void tearDown() { + try { + myClient.cleanup(); + store.dropContainer(TEST_TABLE); + } catch (Exception error) { + // Ignore. + } finally { + myClient = null; + } + } + + /** + * Gets the test DB. + * + * @param props + * Properties to pass to the client. + * @return The test DB. + */ + protected DB getDB(Properties props) { + if( myClient == null ) { + myClient = new GridDBClient(); + myClient.setProperties(props); + try { + myClient.init(); + } catch (Exception error) { + assumeNoException(error); + } + } + return myClient; + } +} diff --git a/pom.xml b/pom.xml index bbb457c2ee..f79864fa2a 100644 --- a/pom.xml +++ b/pom.xml @@ -82,6 +82,7 @@ LICENSE file. 5.2.5 1.2.0 1.4.0 + 4.0.0 0.98.14-hadoop2 1.0.2 1.2.5 @@ -134,6 +135,7 @@ LICENSE file. geode googlebigtable googledatastore + griddb hbase098 hbase10 hbase12