From 661a76d180c6e6d709ef8cb401aeba70ce72d43f Mon Sep 17 00:00:00 2001 From: Jaemyoun <jaemyoun@gmail.com> Date: Sun, 13 Mar 2016 17:34:56 +0900 Subject: [PATCH] first completing rados-binding --- bin/ycsb | 1 + pom.xml | 3 +- rados/pom.xml | 5 + .../java/com/yahoo/ycsb/db/RadosClient.java | 160 ++++++++---------- .../java/com/yahoo/ycsb/db/package-info.java | 20 +++ 5 files changed, 103 insertions(+), 86 deletions(-) diff --git a/bin/ycsb b/bin/ycsb index b731a45f..d92f9f31 100755 --- a/bin/ycsb +++ b/bin/ycsb @@ -76,6 +76,7 @@ DATABASES = { "mongodb-async": "com.yahoo.ycsb.db.AsyncMongoDbClient", "nosqldb" : "com.yahoo.ycsb.db.NoSqlDbClient", "orientdb" : "com.yahoo.ycsb.db.OrientDBClient", + "rados" : "com.yahoo.ycsb.db.RadosClient", "redis" : "com.yahoo.ycsb.db.RedisClient", "s3" : "com.yahoo.ycsb.db.S3Client", "solr" : "com.yahoo.ycsb.db.SolrClient", diff --git a/pom.xml b/pom.xml index 4980e3a9..0badccb5 100644 --- a/pom.xml +++ b/pom.xml @@ -93,7 +93,8 @@ LICENSE file. <tarantool.version>1.6.5</tarantool.version> <aerospike.version>3.1.2</aerospike.version> <solr.version>5.4.0</solr.version> - <rados.version>0.2.0</rados.version> + <rados.version>0.3.0-SNAPSHOT</rados.version> + <json.version>20160212</json.version> </properties> <modules> diff --git a/rados/pom.xml b/rados/pom.xml index f536bb27..902dd3b7 100644 --- a/rados/pom.xml +++ b/rados/pom.xml @@ -24,5 +24,10 @@ <version>${project.version}</version> <scope>provided</scope> </dependency> + <dependency> + <groupId>org.json</groupId> + <artifactId>json</artifactId> + <version>${json.version}</version> + </dependency> </dependencies> </project> diff --git a/rados/src/main/java/com/yahoo/ycsb/db/RadosClient.java b/rados/src/main/java/com/yahoo/ycsb/db/RadosClient.java index 6fd2b885..d3e90252 100644 --- a/rados/src/main/java/com/yahoo/ycsb/db/RadosClient.java +++ b/rados/src/main/java/com/yahoo/ycsb/db/RadosClient.java @@ -1,21 +1,26 @@ package com.yahoo.ycsb.db; +import com.ceph.rados.Rados; +import com.ceph.rados.IoCTX; +import com.ceph.rados.jna.RadosObjectInfo; +import com.ceph.rados.ReadOp; +import com.ceph.rados.ReadOp.ReadResult; +import com.ceph.rados.exceptions.RadosException; + + 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 redis.clients.jedis.Jedis; -import redis.clients.jedis.Protocol; - +import java.io.File; import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Properties; import java.util.Set; import java.util.Vector; +import org.json.JSONObject; + /** * YCSB binding for <a href="http://redis.io/">Redis</a>. * @@ -23,114 +28,99 @@ import java.util.Vector; */ public class RadosClient extends DB { - private static String ENV_CONFIG_FILE = System.getenv("RADOS_JAVA_CONFIG_FILE"); - private static String ENV_ID = System.getenv("RADOS_JAVA_ID"); - private static String ENV_POOL = System.getenv("RADOS_JAVA_POOL"); + // TODO: use conf file + private static String envCONFIGFILE = System.getenv("RADOS_JAVA_CONFIG_FILE"); + private static String envID = System.getenv("RADOS_JAVA_ID"); + private static String envPOOL = System.getenv("RADOS_JAVA_POOL"); - private static final String CONFIG_FILE = ENV_CONFIG_FILE == null ? "/etc/ceph/ceph.conf" : ENV_CONFIG_FILE; - private static final String ID = ENV_ID == null ? "admin" : ENV_ID; - private static final String POOL = ENV_POOL == null ? "data" : ENV_POOL; + private static final String CONFIG_FILE = envCONFIGFILE == null ? "/etc/ceph/ceph.conf" : envCONFIGFILE; + private static final String ID = envID == null ? "admin" : envID; + private static final String POOL = envPOOL == null ? "data" : envPOOL; private static Rados rados; private static IoCTX ioctx; public void init() throws DBException { - Properties props = getProperties(); - int port; - - String portString = props.getProperty(PORT_PROPERTY); - if (portString != null) { - port = Integer.parseInt(portString); - } else { - port = Protocol.DEFAULT_PORT; - } - String host = props.getProperty(HOST_PROPERTY); - - jedis = new Jedis(host, port); - jedis.connect(); - - String password = props.getProperty(PASSWORD_PROPERTY); - if (password != null) { - jedis.auth(password); + rados = new Rados(ID); + try { + rados.confReadFile(new File(CONFIG_FILE)); + rados.connect(); + ioctx = rados.ioCtxCreate(POOL); + } catch (RadosException e) { + throw new DBException(e.getMessage() + ": " + e.getReturnValue()); } } public void cleanup() throws DBException { - jedis.disconnect(); - } - - /* - * Calculate a hash for a key to store it in an index. The actual return value - * of this function is not interesting -- it primarily needs to be fast and - * scattered along the whole space of doubles. In a real world scenario one - * would probably use the ASCII values of the keys. - */ - private double hash(String key) { - return key.hashCode(); + rados.shutDown(); + rados.ioCtxDestroy(ioctx); } - // XXX jedis.select(int index) to switch to `table` - @Override - public Status read(String table, String key, Set<String> fields, - HashMap<String, ByteIterator> result) { - if (fields == null) { - StringByteIterator.putAllAsByteIterators(result, jedis.hgetAll(key)); - } else { - String[] fieldArray = - (String[]) fields.toArray(new String[fields.size()]); - List<String> values = jedis.hmget(key, fieldArray); - - Iterator<String> fieldIterator = fields.iterator(); - Iterator<String> valueIterator = values.iterator(); - - while (fieldIterator.hasNext() && valueIterator.hasNext()) { - result.put(fieldIterator.next(), - new StringByteIterator(valueIterator.next())); + public Status read(String table, String key, Set<String> fields, HashMap<String, ByteIterator> result) { + byte[] buffer; + + try { + RadosObjectInfo info = ioctx.stat(key); + buffer = new byte[(int)info.getSize()]; + + ReadOp rop = ioctx.readOpCreate(); + ReadResult readResult = rop.queueRead(0, info.getSize()); + // TODO: more size than byte length possible; + rop.operate(key, Rados.OPERATION_NOFLAG); + readResult.raiseExceptionOnError("Error ReadOP(%d)", readResult.getRVal()); + if (info.getSize() != readResult.getBytesRead()) { + return new Status("ERROR", "Error the object size read"); } - assert !fieldIterator.hasNext() && !valueIterator.hasNext(); + readResult.getBuffer().get(buffer); + } catch (RadosException e) { + return new Status("ERROR-" + e.getReturnValue(), e.getMessage()); } + + JSONObject json = new JSONObject(new String(buffer, java.nio.charset.StandardCharsets.UTF_8)); + Set<String> fieldsToReturn = (fields == null ? json.keySet() : fields); + + for (String name : fieldsToReturn) { + result.put(name, new StringByteIterator(json.getString(name))); + } + return result.isEmpty() ? Status.ERROR : Status.OK; } @Override - public Status insert(String table, String key, - HashMap<String, ByteIterator> values) { - if (jedis.hmset(key, StringByteIterator.getStringMap(values)) - .equals("OK")) { - jedis.zadd(INDEX_KEY, hash(key), key); - return Status.OK; + public Status insert(String table, String key, HashMap<String, ByteIterator> values) { + JSONObject json = new JSONObject(values); + + try { + ioctx.write(key, json.toString()); + } catch (RadosException e) { + return new Status("ERROR-" + e.getReturnValue(), e.getMessage()); } - return Status.ERROR; + return Status.OK; } @Override public Status delete(String table, String key) { - return jedis.del(key) == 0 && jedis.zrem(INDEX_KEY, key) == 0 ? Status.ERROR - : Status.OK; + try { + ioctx.remove(key); + } catch (RadosException e) { + return new Status("ERROR-" + e.getReturnValue(), e.getMessage()); + } + return Status.OK; } @Override - public Status update(String table, String key, - HashMap<String, ByteIterator> values) { - return jedis.hmset(key, StringByteIterator.getStringMap(values)) - .equals("OK") ? Status.OK : Status.ERROR; + public Status update(String table, String key, HashMap<String, ByteIterator> values) { + Status rtn = delete(table, key); + if (rtn.equals(Status.OK)) { + return insert(table, key, values); + } + return rtn; } @Override - public Status scan(String table, String startkey, int recordcount, - Set<String> fields, Vector<HashMap<String, ByteIterator>> result) { - Set<String> keys = jedis.zrangeByScore(INDEX_KEY, hash(startkey), - Double.POSITIVE_INFINITY, 0, recordcount); - - HashMap<String, ByteIterator> values; - for (String key : keys) { - values = new HashMap<String, ByteIterator>(); - read(table, key, fields, values); - result.add(values); - } - - return Status.OK; + public Status scan(String table, String startkey, int recordcount, Set<String> fields, + Vector<HashMap<String, ByteIterator>> result) { + return Status.NOT_IMPLEMENTED; } - } diff --git a/rados/src/main/java/com/yahoo/ycsb/db/package-info.java b/rados/src/main/java/com/yahoo/ycsb/db/package-info.java index cacae13b..e03a0446 100644 --- a/rados/src/main/java/com/yahoo/ycsb/db/package-info.java +++ b/rados/src/main/java/com/yahoo/ycsb/db/package-info.java @@ -1 +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. + */ + +/** + * YCSB binding for RADOS of Ceph. + */ package com.yahoo.ycsb.db; -- GitLab