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