Summary: In 3.10 the C++ code was extended with a MemEnv implementation. This is now also available in RocksJava. Changes: - Extraced abstract super class Env - Introduced RocksMemEnv - Remove unnecessary disposeInternal method. The disposal of the default environment is managed by C++ so there needs to be no disposeInternal method in Java. - Introduced a RocksMemEnvTest, which is aligned with the C++ equivalent. Test Plan: make rocksdbjava make jtest Reviewers: adamretter, yhchiang, ankgup87 Subscribers: dhruba Differential Revision: https://reviews.facebook.net/D35619main
parent
51da3aab4a
commit
fd8804f979
@ -0,0 +1,92 @@ |
||||
// Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
package org.rocksdb; |
||||
|
||||
/** |
||||
* Base class for all Env implementations in RocksDB. |
||||
*/ |
||||
public abstract class Env extends RocksObject { |
||||
public static final int FLUSH_POOL = 0; |
||||
public static final int COMPACTION_POOL = 1; |
||||
|
||||
/** |
||||
* <p>Returns the default environment suitable for the current operating |
||||
* system.</p> |
||||
* |
||||
* <p>The result of {@code getDefault()} is a singleton whose ownership |
||||
* belongs to rocksdb c++. As a result, the returned RocksEnv will not |
||||
* have the ownership of its c++ resource, and calling its dispose() |
||||
* will be no-op.</p> |
||||
* |
||||
* @return the default {@link org.rocksdb.RocksEnv} instance. |
||||
*/ |
||||
public static Env getDefault() { |
||||
return default_env_; |
||||
} |
||||
|
||||
/** |
||||
* <p>Sets the number of background worker threads of the flush pool |
||||
* for this environment.</p> |
||||
* <p>Default number: 1</p> |
||||
* |
||||
* @param num the number of threads |
||||
* |
||||
* @return current {@link RocksEnv} instance. |
||||
*/ |
||||
public Env setBackgroundThreads(final int num) { |
||||
return setBackgroundThreads(num, FLUSH_POOL); |
||||
} |
||||
|
||||
/** |
||||
* <p>Sets the number of background worker threads of the specified thread |
||||
* pool for this environment.</p> |
||||
* |
||||
* @param num the number of threads |
||||
* @param poolID the id to specified a thread pool. Should be either |
||||
* FLUSH_POOL or COMPACTION_POOL. |
||||
* |
||||
* <p>Default number: 1</p> |
||||
* @return current {@link RocksEnv} instance. |
||||
*/ |
||||
public Env setBackgroundThreads(final int num, final int poolID) { |
||||
setBackgroundThreads(nativeHandle_, num, poolID); |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* <p>Returns the length of the queue associated with the specified |
||||
* thread pool.</p> |
||||
* |
||||
* @param poolID the id to specified a thread pool. Should be either |
||||
* FLUSH_POOL or COMPACTION_POOL. |
||||
* |
||||
* @return the thread pool queue length. |
||||
*/ |
||||
public int getThreadPoolQueueLen(final int poolID) { |
||||
return getThreadPoolQueueLen(nativeHandle_, poolID); |
||||
} |
||||
|
||||
|
||||
protected Env() { |
||||
super(); |
||||
} |
||||
|
||||
static { |
||||
default_env_ = new RocksEnv(getDefaultEnvInternal()); |
||||
} |
||||
|
||||
/** |
||||
* <p>The static default Env. The ownership of its native handle |
||||
* belongs to rocksdb c++ and is not able to be released on the Java |
||||
* side.</p> |
||||
*/ |
||||
static Env default_env_; |
||||
|
||||
private static native long getDefaultEnvInternal(); |
||||
private native void setBackgroundThreads( |
||||
long handle, int num, int priority); |
||||
private native int getThreadPoolQueueLen(long handle, int poolID); |
||||
} |
@ -0,0 +1,33 @@ |
||||
// Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
package org.rocksdb; |
||||
|
||||
/** |
||||
* RocksDB memory environment. |
||||
*/ |
||||
public class RocksMemEnv extends Env { |
||||
|
||||
/** |
||||
* <p>Creates a new RocksDB environment that stores its data |
||||
* in memory and delegates all non-file-storage tasks to |
||||
* base_env. The caller must delete the result when it is |
||||
* no longer needed.</p> |
||||
* |
||||
* <p>{@code *base_env} must remain live while the result is in use.</p> |
||||
*/ |
||||
public RocksMemEnv() { |
||||
super(); |
||||
nativeHandle_ = createMemEnv(); |
||||
} |
||||
|
||||
@Override |
||||
protected void disposeInternal() { |
||||
disposeInternal(nativeHandle_); |
||||
} |
||||
|
||||
private static native long createMemEnv(); |
||||
private native void disposeInternal(long handle); |
||||
} |
@ -0,0 +1,196 @@ |
||||
// Copyright (c) 2015, Facebook, Inc. All rights reserved.
|
||||
// This source code is licensed under the BSD-style license found in the
|
||||
// LICENSE file in the root directory of this source tree. An additional grant
|
||||
// of patent rights can be found in the PATENTS file in the same directory.
|
||||
|
||||
package org.rocksdb; |
||||
|
||||
import org.junit.ClassRule; |
||||
import org.junit.Rule; |
||||
import org.junit.Test; |
||||
import org.junit.rules.TemporaryFolder; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
public class RocksMemEnvTest { |
||||
|
||||
@ClassRule |
||||
public static final RocksMemoryResource rocksMemoryResource = |
||||
new RocksMemoryResource(); |
||||
|
||||
@Test |
||||
public void memEnvFillAndReopen() throws RocksDBException { |
||||
|
||||
final byte[][] keys = { |
||||
"aaa".getBytes(), |
||||
"bbb".getBytes(), |
||||
"ccc".getBytes() |
||||
}; |
||||
|
||||
final byte[][] values = { |
||||
"foo".getBytes(), |
||||
"bar".getBytes(), |
||||
"baz".getBytes() |
||||
}; |
||||
|
||||
Env env = null; |
||||
Options options = null; |
||||
RocksDB db = null; |
||||
FlushOptions flushOptions = null; |
||||
try { |
||||
env = new RocksMemEnv(); |
||||
options = new Options(). |
||||
setCreateIfMissing(true). |
||||
setEnv(env); |
||||
flushOptions = new FlushOptions(). |
||||
setWaitForFlush(true); |
||||
db = RocksDB.open(options, "dir/db"); |
||||
|
||||
// write key/value pairs using MemEnv
|
||||
for (int i=0; i < keys.length; i++) { |
||||
db.put(keys[i], values[i]); |
||||
} |
||||
|
||||
// read key/value pairs using MemEnv
|
||||
for (int i=0; i < keys.length; i++) { |
||||
assertThat(db.get(keys[i])).isEqualTo(values[i]); |
||||
} |
||||
|
||||
// Check iterator access
|
||||
RocksIterator iterator = db.newIterator(); |
||||
iterator.seekToFirst(); |
||||
for (int i=0; i < keys.length; i++) { |
||||
assertThat(iterator.isValid()).isTrue(); |
||||
assertThat(iterator.key()).isEqualTo(keys[i]); |
||||
assertThat(iterator.value()).isEqualTo(values[i]); |
||||
iterator.next(); |
||||
} |
||||
// reached end of database
|
||||
assertThat(iterator.isValid()).isFalse(); |
||||
iterator.dispose(); |
||||
|
||||
// flush
|
||||
db.flush(flushOptions); |
||||
|
||||
// read key/value pairs after flush using MemEnv
|
||||
for (int i=0; i < keys.length; i++) { |
||||
assertThat(db.get(keys[i])).isEqualTo(values[i]); |
||||
} |
||||
|
||||
db.close(); |
||||
options.setCreateIfMissing(false); |
||||
|
||||
// After reopen the values shall still be in the mem env.
|
||||
// as long as the env is not freed.
|
||||
db = RocksDB.open(options, "dir/db"); |
||||
// read key/value pairs using MemEnv
|
||||
for (int i=0; i < keys.length; i++) { |
||||
assertThat(db.get(keys[i])).isEqualTo(values[i]); |
||||
} |
||||
|
||||
} finally { |
||||
if (db != null) { |
||||
db.close(); |
||||
} |
||||
if (options != null) { |
||||
options.dispose(); |
||||
} |
||||
if (flushOptions != null) { |
||||
flushOptions.dispose(); |
||||
} |
||||
if (env != null) { |
||||
env.dispose(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Test |
||||
public void multipleDatabaseInstances() throws RocksDBException { |
||||
// db - keys
|
||||
final byte[][] keys = { |
||||
"aaa".getBytes(), |
||||
"bbb".getBytes(), |
||||
"ccc".getBytes() |
||||
}; |
||||
// otherDb - keys
|
||||
final byte[][] otherKeys = { |
||||
"111".getBytes(), |
||||
"222".getBytes(), |
||||
"333".getBytes() |
||||
}; |
||||
// values
|
||||
final byte[][] values = { |
||||
"foo".getBytes(), |
||||
"bar".getBytes(), |
||||
"baz".getBytes() |
||||
}; |
||||
|
||||
Env env = null; |
||||
Options options = null; |
||||
RocksDB db = null, otherDb = null; |
||||
|
||||
try { |
||||
env = new RocksMemEnv(); |
||||
options = new Options(). |
||||
setCreateIfMissing(true). |
||||
setEnv(env); |
||||
db = RocksDB.open(options, "dir/db"); |
||||
otherDb = RocksDB.open(options, "dir/otherDb"); |
||||
|
||||
// write key/value pairs using MemEnv
|
||||
// to db and to otherDb.
|
||||
for (int i=0; i < keys.length; i++) { |
||||
db.put(keys[i], values[i]); |
||||
otherDb.put(otherKeys[i], values[i]); |
||||
} |
||||
|
||||
// verify key/value pairs after flush using MemEnv
|
||||
for (int i=0; i < keys.length; i++) { |
||||
// verify db
|
||||
assertThat(db.get(otherKeys[i])).isNull(); |
||||
assertThat(db.get(keys[i])).isEqualTo(values[i]); |
||||
|
||||
// verify otherDb
|
||||
assertThat(otherDb.get(keys[i])).isNull(); |
||||
assertThat(otherDb.get(otherKeys[i])).isEqualTo(values[i]); |
||||
} |
||||
} finally { |
||||
if (db != null) { |
||||
db.close(); |
||||
} |
||||
if (otherDb != null) { |
||||
otherDb.close(); |
||||
} |
||||
if (options != null) { |
||||
options.dispose(); |
||||
} |
||||
if (env != null) { |
||||
env.dispose(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Test(expected = RocksDBException.class) |
||||
public void createIfMissingFalse() throws RocksDBException { |
||||
Env env = null; |
||||
Options options = null; |
||||
RocksDB db = null; |
||||
|
||||
try { |
||||
env = new RocksMemEnv(); |
||||
options = new Options(). |
||||
setCreateIfMissing(false). |
||||
setEnv(env); |
||||
// shall throw an exception because db dir does not
|
||||
// exist.
|
||||
db = RocksDB.open(options, "db/dir"); |
||||
} finally { |
||||
if (options != null) { |
||||
options.dispose(); |
||||
} |
||||
if (env != null) { |
||||
env.dispose(); |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue