Skip to content

Commit

Permalink
[orientdb] put db conn stuff in sync method
Browse files Browse the repository at this point in the history
All db connection and creation logic is the same, it is just pulled into
a synchronized method so that multiple threads run through the
connection process one at a time.

Fixes #571
  • Loading branch information
kruthar committed Feb 10, 2016
1 parent 779a703 commit 6116744
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 28 deletions.
9 changes: 9 additions & 0 deletions orientdb/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@ Then, run the workload:

See the next section for the list of configuration parameters for OrientDB.

## DB creation with the OrientDBClient
This client will create a database for you if the connection database you specify does not exists. You can also specify connection information to a preexisting database.

You can use the ```orientdb.newdb=true``` property to allow this client to drop and create a new database instance during the ```load``` phase.

NOTE: understand that using the ```orientdb.newdb=true``` property will drop and recreate databases even if it was a preexisting instance.

WARNING: Creating a new database will be done safely with multiple threads on a single YCSB instance, but is not guaranteed to work when launching multiple YCSB instances. In that scenario it is suggested that you create the db before hand, or run the ```load``` phase with a single YCSB instance.

## OrientDB Configuration Parameters

* ```orientdb.url``` - (required) The address to your database.
Expand Down
80 changes: 52 additions & 28 deletions orientdb/src/main/java/com/yahoo/ycsb/db/OrientDBClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,30 +80,35 @@ public class OrientDBClient extends DB {
private static final String ORIENTDB_MASSIVEREAD = "massiveread";
private static final String ORIENTDB_NOCACHE = "nocache";

private final Logger log = LoggerFactory.getLogger(getClass());

@Override
public void init() throws DBException {
Properties props = getProperties();
private static final Logger LOG = LoggerFactory.getLogger(OrientDBClient.class);

/**
* This method abstracts the administration of OrientDB namely creating and connecting to a database.
* Creating a database needs to be done in a synchronized method so that multiple threads do not all try
* to run the creation operation simultaneously, this ends in failure.
*
* @param props Workload properties object
* @return a usable ODatabaseDocumentTx object
* @throws DBException
*/
private static synchronized ODatabaseDocumentTx initDB(Properties props) throws DBException {
String url = props.getProperty(URL_PROPERTY);
String user = props.getProperty(USER_PROPERTY, USER_PROPERTY_DEFAULT);
String password = props.getProperty(PASSWORD_PROPERTY, PASSWORD_PROPERTY_DEFAULT);
Boolean newdb = Boolean.parseBoolean(props.getProperty(NEWDB_PROPERTY, NEWDB_PROPERTY_DEFAULT));
String remoteStorageType = props.getProperty(STORAGE_TYPE_PROPERTY);
String intent = props.getProperty(INTENT_PROPERTY, INTENT_PROPERTY_DEFAULT);
Boolean dotransactions = Boolean.parseBoolean(
props.getProperty(DO_TRANSACTIONS_PROPERTY, DO_TRANSACTIONS_PROPERTY_DEFAULT));
Boolean isrun = Boolean.parseBoolean(props.getProperty(DO_TRANSACTIONS_PROPERTY, DO_TRANSACTIONS_PROPERTY_DEFAULT));

ODatabaseDocumentTx dbconn;

if (url == null) {
throw new DBException(String.format("Required property \"%s\" missing for OrientDBClient", URL_PROPERTY));
}

log.info("OrientDB loading database url = " + url);
LOG.info("OrientDB loading database url = " + url);

// If using a remote database, use the OServerAdmin interface to connect
if (url.startsWith(OEngineRemote.NAME)) {
isRemote = true;
if (remoteStorageType == null) {
throw new DBException("When connecting to a remote OrientDB instance, " +
"specify a database storage type (plocal or memory) with " + STORAGE_TYPE_PROPERTY);
Expand All @@ -113,54 +118,73 @@ public void init() throws DBException {
OServerAdmin server = new OServerAdmin(url).connect(user, password);

if (server.existsDatabase()) {
if (newdb && !dotransactions) {
log.info("OrientDB dropping and recreating fresh db on remote server.");
if (newdb && !isrun) {
LOG.info("OrientDB dropping and recreating fresh db on remote server.");
server.dropDatabase(remoteStorageType);
server.createDatabase(server.getURL(), ORIENTDB_DOCUMENT_TYPE, remoteStorageType);
}
} else {
log.info("OrientDB database not found, creating fresh db");
LOG.info("OrientDB database not found, creating fresh db");
server.createDatabase(server.getURL(), ORIENTDB_DOCUMENT_TYPE, remoteStorageType);
}

server.close();
db = new ODatabaseDocumentTx(url).open(user, password);
dbconn = new ODatabaseDocumentTx(url).open(user, password);
} catch (IOException | OException e) {
throw new DBException(String.format("Error interfacing with %s", url), e);
}
} else {
try {
db = new ODatabaseDocumentTx(url);
if (db.exists()) {
db.open(user, password);
if (newdb && !dotransactions) {
log.info("OrientDB dropping and recreating fresh db.");
db.drop();
db.create();
dbconn = new ODatabaseDocumentTx(url);
if (dbconn.exists()) {
dbconn.open(user, password);
if (newdb && !isrun) {
LOG.info("OrientDB dropping and recreating fresh db.");
dbconn.drop();
dbconn.create();
}
} else {
log.info("OrientDB database not found, creating fresh db");
db.create();
LOG.info("OrientDB database not found, creating fresh db");
dbconn.create();
}
} catch (ODatabaseException e) {
throw new DBException(String.format("Error interfacing with %s", url), e);
}
}

log.info("OrientDB connection created with " + url);
if (dbconn == null) {
throw new DBException("Could not establish connection to: " + url);
}

LOG.info("OrientDB connection created with " + url);
return dbconn;
}

@Override
public void init() throws DBException {
Properties props = getProperties();

String intent = props.getProperty(INTENT_PROPERTY, INTENT_PROPERTY_DEFAULT);

db = initDB(props);

if (db.getURL().startsWith(OEngineRemote.NAME)) {
isRemote = true;
}

dictionary = db.getMetadata().getIndexManager().getDictionary();
if (!db.getMetadata().getSchema().existsClass(CLASS)) {
db.getMetadata().getSchema().createClass(CLASS);
}

if (intent.equals(ORIENTDB_MASSIVEINSERT)) {
log.info("Declaring intent of MassiveInsert.");
LOG.info("Declaring intent of MassiveInsert.");
db.declareIntent(new OIntentMassiveInsert());
} else if (intent.equals(ORIENTDB_MASSIVEREAD)) {
log.info("Declaring intent of MassiveRead.");
LOG.info("Declaring intent of MassiveRead.");
db.declareIntent(new OIntentMassiveRead());
} else if (intent.equals(ORIENTDB_NOCACHE)) {
log.info("Declaring intent of NoCache.");
LOG.info("Declaring intent of NoCache.");
db.declareIntent(new OIntentNoCache());
}
}
Expand Down Expand Up @@ -248,7 +272,7 @@ public Status scan(String table, String startkey, int recordcount, Set<String> f
Vector<HashMap<String, ByteIterator>> result) {
if (isRemote) {
// Iterator methods needed for scanning are Unsupported for remote database connections.
log.warn("OrientDB scan operation is not implemented for remote database connections.");
LOG.warn("OrientDB scan operation is not implemented for remote database connections.");
return Status.NOT_IMPLEMENTED;
}

Expand Down

0 comments on commit 6116744

Please sign in to comment.