From ea76ee734d84a431834fed3ceb5e101104d01283 Mon Sep 17 00:00:00 2001 From: Luca Garulli <l.garulli@gmail.com> Date: Fri, 11 May 2012 00:59:49 +0200 Subject: [PATCH] gh-76 Implemented OrientDB client --- bin/ycsb | 1 + orientdb/README.md | 31 +++ orientdb/pom.xml | 57 +++++ .../com/yahoo/ycsb/db/OrientDBClient.java | 224 ++++++++++++++++++ pom.xml | 2 + 5 files changed, 315 insertions(+) create mode 100644 orientdb/README.md create mode 100644 orientdb/pom.xml create mode 100644 orientdb/src/main/java/com/yahoo/ycsb/db/OrientDBClient.java diff --git a/bin/ycsb b/bin/ycsb index 1ee3c5ed..0ccd1006 100755 --- a/bin/ycsb +++ b/bin/ycsb @@ -36,6 +36,7 @@ DATABASES = { "mapkeeper" : "com.yahoo.ycsb.db.MapKeeperClient", "mongodb" : "com.yahoo.ycsb.db.MongoDbClient", "nosqldb" : "com.yahoo.ycsb.db.NoSqlDbClient", + "orientdb" : "com.yahoo.ycsb.db.OrientDBClient", "redis" : "com.yahoo.ycsb.db.RedisClient", "voldemort" : "com.yahoo.ycsb.db.VoldemortClient", } diff --git a/orientdb/README.md b/orientdb/README.md new file mode 100644 index 00000000..05211935 --- /dev/null +++ b/orientdb/README.md @@ -0,0 +1,31 @@ +## Quick Start + +This section describes how to run YCSB on OrientDB running locally. + +### 1. Set Up YCSB + +Clone the YCSB git repository and compile: + + git clone git://github.com/nuvolabase/YCSB.git + cd YCSB + mvn clean package + +### 2. Run YCSB + +Now you are ready to run! First, load the data: + + ./bin/ycsb load orientdb -s -P workloads/workloada + +Then, run the workload: + + ./bin/ycsb run orientdb -s -P workloads/workloada + +See the next section for the list of configuration parameters for OrientDB. + +## OrientDB Configuration Parameters + +### `OrientDB.url` (default: `local:C:/temp/databases/ycsb`) + +### `OrientDB.user` (default `admin`) + +### `OrientDB.password` (default `admin`) diff --git a/orientdb/pom.xml b/orientdb/pom.xml new file mode 100644 index 00000000..66c0f6e7 --- /dev/null +++ b/orientdb/pom.xml @@ -0,0 +1,57 @@ +<?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>orientdb-binding</artifactId> + <name>OrientDB Binding</name> + <packaging>jar</packaging> + <repositories> + <repository> + <id>sonatype-nexus-snapshots</id> + <name>Sonatype Nexus Snapshots</name> + <url>https://oss.sonatype.org/content/repositories/snapshots</url> + </repository> + </repositories> + <dependencies> + <dependency> + <groupId>com.yahoo.ycsb</groupId> + <artifactId>core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>com.orientechnologies</groupId> + <artifactId>orientdb-core</artifactId> + <version>1.0-SNAPSHOT</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> diff --git a/orientdb/src/main/java/com/yahoo/ycsb/db/OrientDBClient.java b/orientdb/src/main/java/com/yahoo/ycsb/db/OrientDBClient.java new file mode 100644 index 00000000..490851a7 --- /dev/null +++ b/orientdb/src/main/java/com/yahoo/ycsb/db/OrientDBClient.java @@ -0,0 +1,224 @@ +/** + * OrientDB client binding for YCSB. + * + * Submitted by Luca Garulli on 5/10/2012. + * + */ + +package com.yahoo.ycsb.db; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map.Entry; +import java.util.Properties; +import java.util.Set; +import java.util.Vector; + +import com.orientechnologies.orient.core.config.OGlobalConfiguration; +import com.orientechnologies.orient.core.db.document.ODatabaseDocumentTx; +import com.orientechnologies.orient.core.dictionary.ODictionary; +import com.orientechnologies.orient.core.intent.OIntentMassiveInsert; +import com.orientechnologies.orient.core.record.ORecordInternal; +import com.orientechnologies.orient.core.record.impl.ODocument; +import com.yahoo.ycsb.ByteIterator; +import com.yahoo.ycsb.DB; +import com.yahoo.ycsb.DBException; +import com.yahoo.ycsb.StringByteIterator; + +/** + * OrientDB client for YCSB framework. + * + * Properties to set: + * + * orientdb.url=local:C:/temp/databases or remote:localhost:2424 <br> + * orientdb.database=ycsb <br> + * orientdb.user=admin <br> + * orientdb.password=admin <br> + * + * @author Luca Garulli + * + */ +public class OrientDBClient extends DB { + + private ODatabaseDocumentTx db; + private static final String CLASS = "usertable"; + private ODictionary<ORecordInternal<?>> dictionary; + + /** + * Initialize any state for this DB. Called once per DB instance; there is one DB instance per client thread. + */ + public void init() throws DBException { + // initialize OrientDB driver + Properties props = getProperties(); + + String url = props.getProperty("orientdb.url", "local:C:/temp/databases/ycsb"); + String user = props.getProperty("orientdb.user", "admin"); + String password = props.getProperty("orientdb.password", "admin"); + Boolean newdb = Boolean.parseBoolean(props.getProperty("orientdb.newdb", "false")); + + try { + System.out.println("OrientDB loading database url = " + url); + + OGlobalConfiguration.STORAGE_KEEP_OPEN.setValue(false); + db = new ODatabaseDocumentTx(url); + if (db.exists()) { + db.open(user, password); + if (newdb) { + System.out.println("OrientDB drop and recreate fresh db"); + db.drop(); + db.create(); + } + } else { + System.out.println("OrientDB database not found, create fresh db"); + db.create(); + } + + System.out.println("OrientDB connection created with " + url); + + dictionary = db.getMetadata().getIndexManager().getDictionary(); + if (!db.getMetadata().getSchema().existsClass(CLASS)) + db.getMetadata().getSchema().createClass(CLASS); + + db.declareIntent(new OIntentMassiveInsert()); + + } catch (Exception e1) { + System.err.println("Could not initialize OrientDB connection pool for Loader: " + e1.toString()); + e1.printStackTrace(); + return; + } + + } + + @Override + public void cleanup() throws DBException { + if (db != null) { + db.close(); + db = null; + } + } + + @Override + /** + * Insert a record in the database. Any field/value pairs in the specified values HashMap will be written into the record with the specified + * record key. + * + * @param table The name of the table + * @param key The record key of the record to insert. + * @param values A HashMap of field/value pairs to insert in the record + * @return Zero on success, a non-zero error code on error. See this class's description for a discussion of error codes. + */ + public int insert(String table, String key, HashMap<String, ByteIterator> values) { + try { + final ODocument document = new ODocument(CLASS); + for (Entry<String, String> entry : StringByteIterator.getStringMap(values).entrySet()) + document.field(entry.getKey(), entry.getValue()); + document.save(); + dictionary.put(key, document); + + return 0; + } catch (Exception e) { + e.printStackTrace(); + } + return 1; + } + + @Override + /** + * Delete a record from the database. + * + * @param table The name of the table + * @param key The record key of the record to delete. + * @return Zero on success, a non-zero error code on error. See this class's description for a discussion of error codes. + */ + public int delete(String table, String key) { + try { + dictionary.remove(key); + return 0; + } catch (Exception e) { + e.printStackTrace(); + } + return 1; + } + + @Override + /** + * Read a record from the database. Each field/value pair from the result will be stored in a HashMap. + * + * @param table The name of the table + * @param key The record key of the record to read. + * @param fields The list of fields to read, or null for all of them + * @param result A HashMap of field/value pairs for the result + * @return Zero on success, a non-zero error code on error or "not found". + */ + public int read(String table, String key, Set<String> fields, HashMap<String, ByteIterator> result) { + try { + final ODocument document = dictionary.get(key); + if (document != null) { + if (fields != null) + for (String field : fields) + result.put(field, new StringByteIterator((String) document.field(field))); + else + for (String field : document.fieldNames()) + result.put(field, new StringByteIterator((String) document.field(field))); + return 0; + } + } catch (Exception e) { + e.printStackTrace(); + } + return 1; + } + + @Override + /** + * Update a record in the database. Any field/value pairs in the specified values HashMap will be written into the record with the specified + * record key, overwriting any existing values with the same field name. + * + * @param table The name of the table + * @param key The record key of the record to write. + * @param values A HashMap of field/value pairs to update in the record + * @return Zero on success, a non-zero error code on error. See this class's description for a discussion of error codes. + */ + public int update(String table, String key, HashMap<String, ByteIterator> values) { + try { + final ODocument document = dictionary.get(key); + if (document != null) { + for (Entry<String, String> entry : StringByteIterator.getStringMap(values).entrySet()) + document.field(entry.getKey(), entry.getValue()); + document.save(); + return 0; + } + } catch (Exception e) { + e.printStackTrace(); + } + return 1; + } + + @Override + /** + * Perform a range scan for a set of records in the database. Each field/value pair from the result will be stored in a HashMap. + * + * @param table The name of the table + * @param startkey The record key of the first record to read. + * @param recordcount The number of records to read + * @param fields The list of fields to read, or null for all of them + * @param result A Vector of HashMaps, where each HashMap is a set field/value pairs for one record + * @return Zero on success, a non-zero error code on error. See this class's description for a discussion of error codes. + */ + public int scan(String table, String startkey, int recordcount, Set<String> fields, Vector<HashMap<String, ByteIterator>> result) { + try { + final Collection<ODocument> documents = dictionary.getIndex().getEntriesMajor(startkey, true, recordcount); + for (ODocument document : documents) { + final HashMap<String, ByteIterator> entry = new HashMap<String, ByteIterator>(fields.size()); + result.add(entry); + + for (String field : fields) + entry.put(field, new StringByteIterator((String) document.field(field))); + } + + return 0; + } catch (Exception e) { + e.printStackTrace(); + } + return 1; + } +} diff --git a/pom.xml b/pom.xml index 816d6521..793146a8 100644 --- a/pom.xml +++ b/pom.xml @@ -50,6 +50,7 @@ <openjpa.jdbc.version>2.1.1</openjpa.jdbc.version> <mapkeeper.version>1.0</mapkeeper.version> <mongodb.version>2.8.0</mongodb.version> + <orientdb.version>1.0-SNAPSHOT</orientdb.version> <redis.version>2.0.0</redis.version> <voldemort.version>0.81</voldemort.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> @@ -68,6 +69,7 @@ <module>jdbc</module> <module>mapkeeper</module> <module>mongodb</module> + <module>orientdb</module> <!--module>nosqldb</module--> <module>redis</module> <module>voldemort</module> -- GitLab